using System;
using System.Collections.Generic;
using System.Text;


namespace FaceCat
{
    /// <summary>
    /// 图表
    /// </summary>
    public class FCChart : FCView
    {
        /// <summary>
        /// 创建图表
        /// </summary>
        public FCChart()
        {
            m_indicatorColors.add(FCColor.rgb(100, 100, 100));
            m_indicatorColors.add(FCColor.rgb(206, 147, 27));
            m_indicatorColors.add(FCColor.rgb(150, 0, 150));
            m_indicatorColors.add(FCColor.rgb(255, 0, 0));
            m_indicatorColors.add(FCColor.rgb(0, 150, 150));
            m_indicatorColors.add(FCColor.rgb(0, 150, 0));
            m_indicatorColors.add(FCColor.rgb(59, 174, 218));
            m_indicatorColors.add(FCColor.rgb(50, 50, 50));
        }

        public bool m_autoFillHScale = false; //是否填充满X轴
        public bool m_allowDragChartDiv = false; //是否允许拖拽图层
        public double m_candleMax = 0; //蜡烛线的最大值
        public double m_candleMin = 0; //蜡烛线的最小值
        public double m_candleMaxRight = 0; //蜡烛线的右轴最大值
        public double m_candleMinRight = 0; //蜡烛线的右轴最小值
        public long m_crossTipColor = FCColor.rgb(50, 50, 50); //十字线标识的颜色
        public long m_crossLineColor = FCColor.rgb(100, 100, 100); //十字线的颜色
        public int m_candlePaddingTop = 30; //图表层的上边距
        public int m_candlePaddingBottom = 30; //图表层的下边距
        public int m_candleDigit = 2; //图表层保留小数的位数
        public double m_candleDivPercent = 0.5; //图表层的占比
        public int m_crossStopIndex = -1; //鼠标停留位置
        public String m_cycle = "day"; //周期
        public ArrayList<SecurityData> m_datas = new ArrayList<SecurityData>(); //子节点
        public long m_downColor = FCColor.rgb(15, 193, 118); //下跌颜色
        public int m_firstVisibleIndex = -1; //起始可见的索引
        public long m_gridColor = FCColor.rgb(150, 150, 150); //网格颜色
        public int m_lastVisibleIndex = -1; //结束可见的索引
        public int m_leftVScaleWidth = 80; //左轴宽度
        public bool m_lastRecordIsVisible = true; //最后记录是否可见
        public double m_lastVisibleKey = 0; //最后可见的主键
        public double m_hScalePixel = 11; //蜡烛线的宽度
        public int m_hScaleHeight = 30; //X轴的高度
        public int m_hScaleTextDistance = 10; //X轴的文字间隔
        public String m_hScaleFormat = ""; //X轴的格式化字符，例如YYYY-mm-dd HH:MM:SS
        public double m_indMax = 0; //指标层的最大值
        public double m_indMin = 0; //指标的最小值
        public double m_indMax2 = 0; //指标层2的最大值
        public double m_indMin2 = 0; //指标层2的最小值
        public double m_indMaxRight = 0; //指标层的右轴最大值
        public double m_indMinRight = 0; //指标层的右轴最小值
        public double m_indMax2Right = 0; //指标层2的右轴最大值
        public double m_indMin2Right = 0; //指标层2的右轴最小值
        public int m_indDigit = 2; //指标层保留小数的位数
        public int m_indDigit2 = 2; //指标层2保留小数的位数
        public double m_indDivPercent = 0.3; //指标层的占比
        public double m_indDivPercent2 = 0.0; //指标层2的占比
        public int m_indPaddingTop = 20; //指标层的上边距
        public int m_indPaddingBottom = 20; //指标层的下边距
        public int m_indPaddingTop2 = 20; //指标层2的上边距
        public int m_indPaddingBottom2 = 20; //指标层2的下边距
        public ArrayList<long> m_indicatorColors = new ArrayList<long>(); //扩展图形
        public int m_lastValidIndex = -1; //最后有效数据索引
        public float m_lineWidthChart = 1;
        public String m_mainIndicator = ""; //主图指标
        public int m_magnitude = 1; //成交量的比例
        public long m_midColor = FCColor.None; //中间颜色
        public float m_offsetX = 0; //横向绘图偏移
        public ArrayList<FCPlot> m_plots = new ArrayList<FCPlot>(); //画线
        public int m_plotPointSizeChart = 20; //画线的选中点大小
        public int m_rightVScaleWidth = 0; //右轴宽度
        public int m_rightSpace = 0; //右侧空间
        public long m_scaleColor = FCColor.rgb(100, 100, 100); //刻度的颜色
        public String m_showIndicator = ""; //显示指标
        public String m_showIndicator2 = ""; //显示指标2
        public bool m_showCrossLine = false; //是否显示十字线
        public int m_selectPlotPoint = -1; //选中画线的点
        public bool m_startMovePlot = false; //选中画线
        public String m_selectShape = ""; //选中的图形
        public String m_selectShapeEx = ""; //选中的图形信息
        public ArrayList<BaseShape> m_shapes = new ArrayList<BaseShape>(); //扩展图形
        public FCPlot m_sPlot = null; //选中的线条
        public float m_targetOldX = 0; //缩小时旧的位置1
        public float m_targetOldX2 = 0; //放大时旧的位置2
        public FCPoint m_touchPosition = new FCPoint(0, 0); //鼠标坐标
	    public long m_trendColor = FCColor.rgb(0, 0, 0); //分时线颜色
        public double m_volMax = 0; //成交量层的最大值
        public double m_volMin = 0; //成交量层的最小值
        public double m_volMaxRight = 0; //成交量层的右轴最大值
        public double m_volMinRight = 0; //成交量层的右轴最小值
        public int m_volDigit = 0; //成交量层保留小数的位数
        public double m_volDivPercent = 0.2; //成交量层的占比
        public int m_volPaddingTop = 20; //成交量层的上边距
        public int m_volPaddingBottom = 0; //成交量层的下边距
        public int m_vScaleDistance = 35; //纵轴的间隔
        public String m_vScaleType = "standard"; //纵轴的类型 log10代表指数坐标
        public long m_upColor = FCColor.rgb(219, 68, 83); //上涨颜色
        public double m_kChart = 0;
        public double m_bChart = 0;
        public double m_oXChart = 0;
        public double m_oYChart = 0;
        public double m_rChart = 0;
        public double m_gridStep = 0; //网格计算临时变量
        public int m_gridDigit = 0; //网格计算临时变量
        //拖动滚动的缓存
        public int m_firstIndexCache = -1;
        public int m_firstTouchIndexCache = -1;
        public FCPoint m_firstTouchPointCache = new FCPoint(0, 0);
        public int m_lastIndexCache = -1;
        public int m_secondTouchIndexCache = -1;
        public FCPoint m_secondTouchPointCache = new FCPoint(0, 0);
        public int m_firstPaddingTop = 0;
        public int m_firtstPaddingBottom = 0;
        public FCPoint m_touchDownPoint = new FCPoint(0, 0);
        public String m_addingPlot = "";
        public double m_x4Chart = 0;
        public double m_y4Chart = 0;
        public double m_nHighChart = 0;
        public double m_nLowChart = 0;
        public double m_xChart = 0;
        public double m_yChart = 0;
        public double m_wChart = 0;
        public double m_hChart = 0;
        public double m_upSubValue = 0;
        public double m_downSubValue = 0;
        public String m_candleStyle = "rect";
        public String m_barStyle = "rect";
        public double m_firstOpen;
        public long m_vScaleTextColor = FCColor.None;
        public long m_hScaleTextColor = FCColor.None;
        public ArrayList<double> m_allema12 = new ArrayList<double>();
        public ArrayList<double> m_allema26 = new ArrayList<double>();
        public ArrayList<double> m_alldifarr = new ArrayList<double>();
        public ArrayList<double> m_alldeaarr = new ArrayList<double>();
        public ArrayList<double> m_allmacdarr = new ArrayList<double>();
        public ArrayList<double> m_bollUp = new ArrayList<double>();
        public ArrayList<double> m_bollDown = new ArrayList<double>();
        public ArrayList<double> m_bollMid = new ArrayList<double>();
        public ArrayList<double> m_bias1 = new ArrayList<double>();
        public ArrayList<double> m_bias2 = new ArrayList<double>();
        public ArrayList<double> m_bias3 = new ArrayList<double>();
        public ArrayList<double> m_kdjK = new ArrayList<double>();
        public ArrayList<double> m_kdjD = new ArrayList<double>();
        public ArrayList<double> m_kdjJ = new ArrayList<double>();
        public ArrayList<double> m_rsi1 = new ArrayList<double>();
        public ArrayList<double> m_rsi2 = new ArrayList<double>();
        public ArrayList<double> m_rsi3 = new ArrayList<double>();
        public ArrayList<double> m_roc = new ArrayList<double>();
        public ArrayList<double> m_rocMa = new ArrayList<double>();
        public ArrayList<double> m_wr1 = new ArrayList<double>();
        public ArrayList<double> m_wr2 = new ArrayList<double>();
        public ArrayList<double> m_cci = new ArrayList<double>();
        public ArrayList<double> m_bbi = new ArrayList<double>();
        public ArrayList<double> m_trix = new ArrayList<double>();
        public ArrayList<double> m_trixMa = new ArrayList<double>();
        public ArrayList<double> m_dma1 = new ArrayList<double>();
        public ArrayList<double> m_dma2 = new ArrayList<double>();
        public ArrayList<double> m_ma5 = new ArrayList<double>();
        public ArrayList<double> m_ma10 = new ArrayList<double>();
        public ArrayList<double> m_ma20 = new ArrayList<double>();
        public ArrayList<double> m_ma30 = new ArrayList<double>();
        public ArrayList<double> m_ma120 = new ArrayList<double>();
        public ArrayList<double> m_ma250 = new ArrayList<double>();
        public ArrayList<double> m_closeArr = new ArrayList<double>();

        /// <summary>
        /// 添加画线
        /// </summary>
        /// <param name="firstTouch">是否第一次触摸</param>
        /// <param name="firstPoint">第一次触摸的坐标</param>
        /// <param name="secondTouch">是否第二次触摸</param>
        /// <param name="secondPoint">第二次触摸的坐标</param>
        public virtual void addPlotDefault(bool firstTouch, FCPoint firstPoint, bool secondTouch, FCPoint secondPoint, String darkOrLight)
        {
            FCPoint mp = firstPoint;
            if (mp.y < getCandleDivHeight())
            {
                int touchIndex = getChartIndex(mp);
                if (touchIndex >= m_firstVisibleIndex &&
                    touchIndex <= m_lastVisibleIndex)
                {
                    if (m_addingPlot == "FiboTimezone")
                    {
                        int fIndex = touchIndex;
                        double fDate = getChartDateByIndex(fIndex);
                        double y = getChartValue(mp);
                        FCPlot newPlot = new FCPlot();
                        if (darkOrLight == "light")
                        {
                            newPlot.m_lineColor = FCColor.rgb(0, 0, 0);
                            newPlot.m_pointColor = FCColor.rgba(0, 0, 0, 125);
                        }
                        else
                        {
                            newPlot.m_lineColor = FCColor.rgb(255, 255, 255);
                            newPlot.m_pointColor = FCColor.rgba(255, 255, 255, 125);
                        }
                        newPlot.m_key1 = fDate;
                        newPlot.m_value1 = y;
                        newPlot.m_plotType = m_addingPlot;
                        m_plots.add(newPlot);
                        m_sPlot = null;
                        FCPlot selectedPlot = selectPlot(mp);
                        if (selectedPlot != null)
                        {
                            m_sPlot = selectedPlot;
                        }
                    }
                    else if (m_addingPlot == "Triangle" ||
                        m_addingPlot == "CircumCycle" ||
                        m_addingPlot == "ParalleGram" ||
                        m_addingPlot == "AngleLine" ||
                        m_addingPlot == "Parallel" ||
                        m_addingPlot == "SymmetricTriangle")
                    {
                        int eIndex = touchIndex;
                        int bIndex = eIndex - 5;
                        if (bIndex >= 0)
                        {
                            double fDate = getChartDateByIndex(bIndex);
                            double sDate = getChartDateByIndex(eIndex);
                            double y = getChartValue(mp);
                            FCPlot newPlot = new FCPlot();
                            if (darkOrLight == "light")
                            {
                                newPlot.m_lineColor = FCColor.rgb(0, 0, 0);
                                newPlot.m_pointColor = FCColor.rgba(0, 0, 0, 125);
                            }
                            else
                            {
                                newPlot.m_lineColor = FCColor.rgb(255, 255, 255);
                                newPlot.m_pointColor = FCColor.rgba(255, 255, 255, 125);
                            }
                            newPlot.m_key1 = fDate;
                            newPlot.m_value1 = y;
                            newPlot.m_key2 = sDate;
                            newPlot.m_value2 = y;
                            newPlot.m_key3 = sDate;
                            newPlot.m_value3 =
                                m_candleMin + (m_candleMax - m_candleMin) / 2;
                            newPlot.m_plotType = m_addingPlot;
                            m_plots.add(newPlot);
                            m_sPlot = null;
                            FCPlot selectedPlot = selectPlot(mp);
                            if (selectedPlot != null)
                            {
                                m_sPlot = selectedPlot;
                            }
                        }
                    }
                    else
                    {
                        int eIndex = touchIndex;
                        int bIndex = eIndex - 5;
                        if (bIndex >= 0)
                        {
                            double fDate = getChartDateByIndex(bIndex);
                            double sDate = getChartDateByIndex(eIndex);
                            double y = getChartValue(mp);
                            FCPlot newPlot = new FCPlot();
                            if (darkOrLight == "light")
                            {
                                newPlot.m_lineColor = FCColor.rgb(0, 0, 0);
                                newPlot.m_pointColor = FCColor.rgba(0, 0, 0, 125);
                            }
                            else
                            {
                                newPlot.m_lineColor = FCColor.rgb(255, 255, 255);
                                newPlot.m_pointColor = FCColor.rgba(255, 255, 255, 125);
                            }
                            newPlot.m_key1 = fDate;
                            newPlot.m_value1 = y;
                            newPlot.m_key2 = sDate;
                            newPlot.m_value2 = y;
                            newPlot.m_plotType = m_addingPlot;
                            m_plots.add(newPlot);
                            m_sPlot = null;
                            FCPlot selectedPlot = selectPlot(mp);
                            if (selectedPlot != null)
                            {
                                m_sPlot = selectedPlot;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 计算平均值
        /// </summary>
        /// <param name="list">集合</param>
        /// <returns></returns>
        public virtual double avgValue(ArrayList<double> list)
        {
            double sum = 0;
            int length = list.size();
            if (length > 0)
            {
                for (int i = 0; i < length; i++)
                {
                    sum += list[i];
                }
                return sum / length;
            }
            return 0;
        }

        /// <summary>
        /// 计算坐标轴
        /// </summary>
        /// <param name="min">最小值</param>
        /// <param name="max">最大值</param>
        /// <param name="yLen">长度</param>
        /// <param name="maxSpan">最大间隔</param>
        /// <param name="minSpan">最小间隔</param>
        /// <param name="defCount">数量</param>
        /// <returns></returns>
        public virtual double chartGridScale(double min, double max, int yLen, double maxSpan, double minSpan, int defCount)
        {
            double sub = max - min;
            int nMinCount = (int)Math.Ceiling(yLen / maxSpan);
            int nMaxCount = (int)Math.Floor(yLen / minSpan);
            int nCount = defCount;
            double logStep = sub / nCount;
            bool start = false;
            double divisor = 0;
            int i = 0, nTemp = 0;
            m_gridStep = 0;
            m_gridDigit = 0;
            nCount = nMinCount > nCount ? nMinCount : nCount;
            nCount = nMaxCount > nCount ? nCount : nMaxCount;
            nCount = nCount > 1 ? nCount : 1;
            for (i = 15; i >= -6; i--)
            {
                divisor = Math.Pow(10, i);
                if (divisor < 1)
                {
                    m_gridDigit++;
                }
                nTemp = (int)Math.Floor(logStep / divisor);
                if (start)
                {
                    if (nTemp < 4)
                    {
                        if (m_gridDigit > 0)
                        {
                            m_gridDigit--;
                        }
                    }
                    else if (nTemp >= 4 && nTemp <= 6)
                    {
                        nTemp = 5;
                        m_gridStep += nTemp * divisor;
                    }
                    else
                    {
                        m_gridStep += 10 * divisor;
                        if (m_gridDigit > 0)
                        {
                            m_gridDigit--;
                        }
                    }
                    break;
                }
                else if (nTemp > 0)
                {
                    m_gridStep = nTemp * divisor + m_gridStep;
                    logStep -= m_gridStep;
                    start = true;
                }
            }
            return 0;
        }

        /// <summary>
        /// 计算最大最小值
        /// </summary>
        public virtual void calculateChartMaxMin()
        {
            m_candleMax = 0;
            m_candleMin = 0;
            m_volMax = 0;
            m_volMin = 0;
            m_indMin = 0;
            m_indMin = 0;
            bool load1 = false;
            bool load2 = false;
            bool load3 = false;
            bool load4 = false;
            bool isTrend = m_cycle == "trend";
            double firstOpen = m_firstOpen;
            if (m_datas.size() > 0)
            {
                int lastValidIndex = m_lastVisibleIndex;
                if (m_lastValidIndex != -1)
                {
                    lastValidIndex = m_lastValidIndex;
                }
                for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
                {
                    if (i == m_firstVisibleIndex)
                    {
                        if (isTrend)
                        {
                            m_candleMax = m_datas[i].m_close;
                            m_candleMin = m_datas[i].m_close;
                            if (firstOpen == 0)
                            {
                                firstOpen = m_datas[i].m_close;
                            }
                        }
                        else
                        {
                            m_candleMax = m_datas[i].m_high;
                            m_candleMin = m_datas[i].m_low;
                        }
                        m_volMax = m_datas[i].m_volume;
                        load1 = true;
                        load2 = true;
                        if (m_showIndicator == "MACD")
                        {
                            m_indMax = m_alldifarr[i];
                            m_indMin = m_alldifarr[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "KDJ")
                        {
                            m_indMax = m_kdjK[i];
                            m_indMin = m_kdjK[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "RSI")
                        {
                            m_indMax = m_rsi1[i];
                            m_indMin = m_rsi1[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "BIAS")
                        {
                            m_indMax = m_bias1[i];
                            m_indMin = m_bias1[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "ROC")
                        {
                            m_indMax = m_roc[i];
                            m_indMin = m_roc[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "WR")
                        {
                            m_indMax = m_wr1[i];
                            m_indMin = m_wr1[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "CCI")
                        {
                            m_indMax = m_cci[i];
                            m_indMin = m_cci[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "BBI")
                        {
                            m_indMax = m_bbi[i];
                            m_indMin = m_bbi[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "TRIX")
                        {
                            m_indMax = m_trix[i];
                            m_indMin = m_trix[i];
                            load3 = true;
                        }
                        else if (m_showIndicator == "DMA")
                        {
                            m_indMax = m_dma1[i];
                            m_indMin = m_dma1[i];
                            load3 = true;
                        }

                        if (m_showIndicator2 == "MACD")
                        {
                            m_indMax2 = m_alldifarr[i];
                            m_indMin2 = m_alldifarr[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "KDJ")
                        {
                            m_indMax2 = m_kdjK[i];
                            m_indMin2 = m_kdjK[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "RSI")
                        {
                            m_indMax2 = m_rsi1[i];
                            m_indMin2 = m_rsi1[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "BIAS")
                        {
                            m_indMax2 = m_bias1[i];
                            m_indMin2 = m_bias1[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "ROC")
                        {
                            m_indMax2 = m_roc[i];
                            m_indMin2 = m_roc[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "WR")
                        {
                            m_indMax2 = m_wr1[i];
                            m_indMin2 = m_wr1[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "CCI")
                        {
                            m_indMax2 = m_cci[i];
                            m_indMin2 = m_cci[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "BBI")
                        {
                            m_indMax2 = m_bbi[i];
                            m_indMin2 = m_bbi[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "TRIX")
                        {
                            m_indMax2 = m_trix[i];
                            m_indMin2 = m_trix[i];
                            load4 = true;
                        }
                        else if (m_showIndicator2 == "DMA")
                        {
                            m_indMax2 = m_dma1[i];
                            m_indMin2 = m_dma1[i];
                            load4 = true;
                        }
                    }
                    else
                    {
                        if (isTrend)
                        {
                            if (m_candleMax < m_datas[i].m_close)
                            {
                                m_candleMax = m_datas[i].m_close;
                            }
                            if (m_candleMin > m_datas[i].m_close)
                            {
                                m_candleMin = m_datas[i].m_close;
                            }
                        }
                        else
                        {
                            if (m_candleMax < m_datas[i].m_high)
                            {
                                m_candleMax = m_datas[i].m_high;
                            }
                            if (m_candleMin > m_datas[i].m_low)
                            {
                                m_candleMin = m_datas[i].m_low;
                            }
                        }
                        if (m_volMax < m_datas[i].m_volume)
                        {
                            m_volMax = m_datas[i].m_volume;
                        }
                    }
                    if (m_showIndicator == "MACD")
                    {
                        if (m_indMax < m_alldifarr[i])
                        {
                            m_indMax = m_alldifarr[i];
                        }
                        if (m_indMax < m_alldeaarr[i])
                        {
                            m_indMax = m_alldeaarr[i];
                        }
                        if (m_indMax < m_allmacdarr[i])
                        {
                            m_indMax = m_allmacdarr[i];
                        }
                        if (m_indMin > m_alldifarr[i])
                        {
                            m_indMin = m_alldifarr[i];
                        }
                        if (m_indMin > m_alldeaarr[i])
                        {
                            m_indMin = m_alldeaarr[i];
                        }
                        if (m_indMin > m_allmacdarr[i])
                        {
                            m_indMin = m_allmacdarr[i];
                        }
                    }
                    else if (m_showIndicator == "KDJ")
                    {
                        if (m_indMax < m_kdjK[i])
                        {
                            m_indMax = m_kdjK[i];
                        }
                        if (m_indMax < m_kdjD[i])
                        {
                            m_indMax = m_kdjD[i];
                        }
                        if (m_indMax < m_kdjJ[i])
                        {
                            m_indMax = m_kdjJ[i];
                        }
                        if (m_indMin > m_kdjK[i])
                        {
                            m_indMin = m_kdjK[i];
                        }
                        if (m_indMin > m_kdjD[i])
                        {
                            m_indMin = m_kdjD[i];
                        }
                        if (m_indMin > m_kdjJ[i])
                        {
                            m_indMin = m_kdjJ[i];
                        }
                    }
                    else if (m_showIndicator == "RSI")
                    {
                        if (m_indMax < m_rsi1[i])
                        {
                            m_indMax = m_rsi1[i];
                        }
                        if (m_indMax < m_rsi2[i])
                        {
                            m_indMax = m_rsi2[i];
                        }
                        if (m_indMax < m_rsi3[i])
                        {
                            m_indMax = m_rsi3[i];
                        }
                        if (m_indMin > m_rsi1[i])
                        {
                            m_indMin = m_rsi1[i];
                        }
                        if (m_indMin > m_rsi2[i])
                        {
                            m_indMin = m_rsi2[i];
                        }
                        if (m_indMin > m_rsi3[i])
                        {
                            m_indMin = m_rsi3[i];
                        }
                    }
                    else if (m_showIndicator == "BIAS")
                    {
                        if (m_indMax < m_bias1[i])
                        {
                            m_indMax = m_bias1[i];
                        }
                        if (m_indMax < m_bias2[i])
                        {
                            m_indMax = m_bias2[i];
                        }
                        if (m_indMax < m_bias3[i])
                        {
                            m_indMax = m_bias3[i];
                        }
                        if (m_indMin > m_bias1[i])
                        {
                            m_indMin = m_bias1[i];
                        }
                        if (m_indMin > m_bias2[i])
                        {
                            m_indMin = m_bias2[i];
                        }
                        if (m_indMin > m_bias3[i])
                        {
                            m_indMin = m_bias3[i];
                        }
                    }
                    else if (m_showIndicator == "ROC")
                    {
                        if (m_indMax < m_roc[i])
                        {
                            m_indMax = m_roc[i];
                        }
                        if (m_indMax < m_rocMa[i])
                        {
                            m_indMax = m_rocMa[i];
                        }
                        if (m_indMin > m_roc[i])
                        {
                            m_indMin = m_roc[i];
                        }
                        if (m_indMin > m_rocMa[i])
                        {
                            m_indMin = m_rocMa[i];
                        }
                    }
                    else if (m_showIndicator == "WR")
                    {
                        if (m_indMax < m_wr1[i])
                        {
                            m_indMax = m_wr1[i];
                        }
                        if (m_indMax < m_wr2[i])
                        {
                            m_indMax = m_wr2[i];
                        }
                        if (m_indMin > m_wr1[i])
                        {
                            m_indMin = m_wr1[i];
                        }
                        if (m_indMin > m_wr2[i])
                        {
                            m_indMin = m_wr2[i];
                        }
                    }
                    else if (m_showIndicator == "CCI")
                    {
                        if (m_indMax < m_cci[i])
                        {
                            m_indMax = m_cci[i];
                        }
                        if (m_indMin > m_cci[i])
                        {
                            m_indMin = m_cci[i];
                        }
                    }
                    else if (m_showIndicator == "BBI")
                    {
                        if (m_indMax < m_bbi[i])
                        {
                            m_indMax = m_bbi[i];
                        }
                        if (m_indMin > m_bbi[i])
                        {
                            m_indMin = m_bbi[i];
                        }
                    }
                    else if (m_showIndicator == "TRIX")
                    {
                        if (m_indMax < m_trix[i])
                        {
                            m_indMax = m_trix[i];
                        }
                        if (m_indMax < m_trixMa[i])
                        {
                            m_indMax = m_trixMa[i];
                        }
                        if (m_indMin > m_trix[i])
                        {
                            m_indMin = m_trix[i];
                        }
                        if (m_indMin > m_trixMa[i])
                        {
                            m_indMin = m_trixMa[i];
                        }
                    }
                    else if (m_showIndicator == "DMA")
                    {
                        if (m_indMax < m_dma1[i])
                        {
                            m_indMax = m_dma1[i];
                        }
                        if (m_indMax < m_dma2[i])
                        {
                            m_indMax = m_dma2[i];
                        }
                        if (m_indMin > m_dma1[i])
                        {
                            m_indMin = m_dma1[i];
                        }
                        if (m_indMin > m_dma2[i])
                        {
                            m_indMin = m_dma2[i];
                        }
                    }
                    if (m_showIndicator2 == "MACD")
                    {
                        if (m_indMax2 < m_alldifarr[i])
                        {
                            m_indMax2 = m_alldifarr[i];
                        }
                        if (m_indMax2 < m_alldeaarr[i])
                        {
                            m_indMax2 = m_alldeaarr[i];
                        }
                        if (m_indMax2 < m_allmacdarr[i])
                        {
                            m_indMax2 = m_allmacdarr[i];
                        }
                        if (m_indMin2 > m_alldifarr[i])
                        {
                            m_indMin2 = m_alldifarr[i];
                        }
                        if (m_indMin2 > m_alldeaarr[i])
                        {
                            m_indMin2 = m_alldeaarr[i];
                        }
                        if (m_indMin2 > m_allmacdarr[i])
                        {
                            m_indMin2 = m_allmacdarr[i];
                        }
                    }
                    else if (m_showIndicator2 == "KDJ")
                    {
                        if (m_indMax2 < m_kdjK[i])
                        {
                            m_indMax2 = m_kdjK[i];
                        }
                        if (m_indMax2 < m_kdjD[i])
                        {
                            m_indMax2 = m_kdjD[i];
                        }
                        if (m_indMax2 < m_kdjJ[i])
                        {
                            m_indMax2 = m_kdjJ[i];
                        }
                        if (m_indMin2 > m_kdjK[i])
                        {
                            m_indMin2 = m_kdjK[i];
                        }
                        if (m_indMin2 > m_kdjD[i])
                        {
                            m_indMin2 = m_kdjD[i];
                        }
                        if (m_indMin2 > m_kdjJ[i])
                        {
                            m_indMin2 = m_kdjJ[i];
                        }
                    }
                    else if (m_showIndicator2 == "RSI")
                    {
                        if (m_indMax2 < m_rsi1[i])
                        {
                            m_indMax2 = m_rsi1[i];
                        }
                        if (m_indMax2 < m_rsi2[i])
                        {
                            m_indMax2 = m_rsi2[i];
                        }
                        if (m_indMax2 < m_rsi3[i])
                        {
                            m_indMax = m_rsi3[i];
                        }
                        if (m_indMin2 > m_rsi1[i])
                        {
                            m_indMin2 = m_rsi1[i];
                        }
                        if (m_indMin2 > m_rsi2[i])
                        {
                            m_indMin2 = m_rsi2[i];
                        }
                        if (m_indMin2 > m_rsi3[i])
                        {
                            m_indMin2 = m_rsi3[i];
                        }
                    }
                    else if (m_showIndicator2 == "BIAS")
                    {
                        if (m_indMax2 < m_bias1[i])
                        {
                            m_indMax2 = m_bias1[i];
                        }
                        if (m_indMax2 < m_bias2[i])
                        {
                            m_indMax2 = m_bias2[i];
                        }
                        if (m_indMax2 < m_bias3[i])
                        {
                            m_indMax2 = m_bias3[i];
                        }
                        if (m_indMin2 > m_bias1[i])
                        {
                            m_indMin2 = m_bias1[i];
                        }
                        if (m_indMin2 > m_bias2[i])
                        {
                            m_indMin2 = m_bias2[i];
                        }
                        if (m_indMin2 > m_bias3[i])
                        {
                            m_indMin2 = m_bias3[i];
                        }
                    }
                    else if (m_showIndicator2 == "ROC")
                    {
                        if (m_indMax2 < m_roc[i])
                        {
                            m_indMax2 = m_roc[i];
                        }
                        if (m_indMax2 < m_rocMa[i])
                        {
                            m_indMax2 = m_rocMa[i];
                        }
                        if (m_indMin2 > m_roc[i])
                        {
                            m_indMin2 = m_roc[i];
                        }
                        if (m_indMin2 > m_rocMa[i])
                        {
                            m_indMin2 = m_rocMa[i];
                        }
                    }
                    else if (m_showIndicator2 == "WR")
                    {
                        if (m_indMax2 < m_wr1[i])
                        {
                            m_indMax2 = m_wr1[i];
                        }
                        if (m_indMax2 < m_wr2[i])
                        {
                            m_indMax2 = m_wr2[i];
                        }
                        if (m_indMin2 > m_wr1[i])
                        {
                            m_indMin2 = m_wr1[i];
                        }
                        if (m_indMin2 > m_wr2[i])
                        {
                            m_indMin2 = m_wr2[i];
                        }
                    }
                    else if (m_showIndicator2 == "CCI")
                    {
                        if (m_indMax2 < m_cci[i])
                        {
                            m_indMax2 = m_cci[i];
                        }
                        if (m_indMin2 > m_cci[i])
                        {
                            m_indMin2 = m_cci[i];
                        }
                    }
                    else if (m_showIndicator2 == "BBI")
                    {
                        if (m_indMax2 < m_bbi[i])
                        {
                            m_indMax2 = m_bbi[i];
                        }
                        if (m_indMin2 > m_bbi[i])
                        {
                            m_indMin2 = m_bbi[i];
                        }
                    }
                    else if (m_showIndicator2 == "TRIX")
                    {
                        if (m_indMax2 < m_trix[i])
                        {
                            m_indMax2 = m_trix[i];
                        }
                        if (m_indMax2 < m_trixMa[i])
                        {
                            m_indMax2 = m_trixMa[i];
                        }
                        if (m_indMin2 > m_trix[i])
                        {
                            m_indMin2 = m_trix[i];
                        }
                        if (m_indMin2 > m_trixMa[i])
                        {
                            m_indMin2 = m_trixMa[i];
                        }
                    }
                    else if (m_showIndicator2 == "DMA")
                    {
                        if (m_indMax2 < m_dma1[i])
                        {
                            m_indMax2 = m_dma1[i];
                        }
                        if (m_indMax2 < m_dma2[i])
                        {
                            m_indMax2 = m_dma2[i];
                        }
                        if (m_indMin2 > m_dma1[i])
                        {
                            m_indMin2 = m_dma1[i];
                        }
                        if (m_indMin2 > m_dma2[i])
                        {
                            m_indMin2 = m_dma2[i];
                        }
                    }
                }
            }
            if (m_shapes.size() > 0)
            {
                int lastValidIndex = m_lastVisibleIndex;
                if (m_lastValidIndex != -1)
                {
                    lastValidIndex = m_lastValidIndex;
                }
                for (int s = 0; s < m_shapes.size(); s++)
                {
                    BaseShape shape = m_shapes[s];
                    if (shape.m_datas.size() > 0)
                    {
                        for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
                        {
                            if (shape.m_divIndex == 0)
                            {
                                if (!load1 && i == m_firstVisibleIndex)
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        m_candleMax = shape.m_datas[i];
                                        m_candleMin = shape.m_datas[i];
                                    }
                                    else
                                    {
                                        m_candleMaxRight = shape.m_datas[i];
                                        m_candleMinRight = shape.m_datas[i];
                                    }
                                    load1 = true;
                                }
                                else
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        if (shape.m_datas[i] > m_candleMax)
                                        {
                                            m_candleMax = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_candleMin)
                                        {
                                            m_candleMin = shape.m_datas[i];
                                        }
                                    }
                                    else
                                    {
                                        if (shape.m_datas[i] > m_candleMaxRight)
                                        {
                                            m_candleMaxRight = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_candleMinRight)
                                        {
                                            m_candleMinRight = shape.m_datas[i];
                                        }
                                    }
                                }
                            }
                            else if (shape.m_divIndex == 1)
                            {
                                if (!load2 && i == m_firstVisibleIndex)
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        m_volMax = shape.m_datas[i];
                                        m_volMin = shape.m_datas[i];
                                    }
                                    else
                                    {
                                        m_volMaxRight = shape.m_datas[i];
                                        m_volMinRight = shape.m_datas[i];
                                    }
                                    load2 = true;
                                }
                                else
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        if (shape.m_datas[i] > m_volMax)
                                        {
                                            m_volMax = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_volMin)
                                        {
                                            m_volMin = shape.m_datas[i];
                                        }
                                    }
                                    else
                                    {
                                        if (shape.m_datas[i] > m_volMaxRight)
                                        {
                                            m_volMaxRight = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_volMinRight)
                                        {
                                            m_volMinRight = shape.m_datas[i];
                                        }
                                    }
                                }
                            }
                            else if (shape.m_divIndex == 2)
                            {
                                if (!load3 && i == m_firstVisibleIndex)
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        m_indMax = shape.m_datas[i];
                                        m_indMin = shape.m_datas[i];
                                    }
                                    else
                                    {
                                        m_indMaxRight = shape.m_datas[i];
                                        m_indMinRight = shape.m_datas[i];
                                    }
                                    load3 = true;
                                }
                                else
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        if (shape.m_datas[i] > m_indMax)
                                        {
                                            m_indMax = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_indMin)
                                        {
                                            m_indMin = shape.m_datas[i];
                                        }
                                    }
                                    else
                                    {
                                        if (shape.m_datas[i] > m_indMaxRight)
                                        {
                                            m_indMaxRight = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_indMinRight)
                                        {
                                            m_indMinRight = shape.m_datas[i];
                                        }
                                    }
                                }
                            }
                            else if (shape.m_divIndex == 3)
                            {
                                if (!load4 && i == m_firstVisibleIndex)
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        m_indMax2 = shape.m_datas[i];
                                        m_indMin2 = shape.m_datas[i];
                                    }
                                    else
                                    {
                                        m_indMax2Right = shape.m_datas[i];
                                        m_indMin2Right = shape.m_datas[i];
                                    }
                                    load4 = true;
                                }
                                else
                                {
                                    if (shape.m_leftOrRight)
                                    {
                                        if (shape.m_datas[i] > m_indMax2)
                                        {
                                            m_indMax2 = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_indMin2)
                                        {
                                            m_indMin2 = shape.m_datas[i];
                                        }
                                    }
                                    else
                                    {
                                        if (shape.m_datas[i] > m_indMax2Right)
                                        {
                                            m_indMax2Right = shape.m_datas[i];
                                        }
                                        if (shape.m_datas[i] < m_indMin2Right)
                                        {
                                            m_indMin2Right = shape.m_datas[i];
                                        }
                                    }
                                }
                            }
                        }
                    }
                    if (shape.m_datas2.size() > 0)
                    {
                        for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
                        {
                            if (shape.m_divIndex == 0)
                            {
                                if (shape.m_leftOrRight)
                                {
                                    if (shape.m_datas2[i] > m_candleMax)
                                    {
                                        m_candleMax = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_candleMin)
                                    {
                                        m_candleMin = shape.m_datas2[i];
                                    }
                                }
                                else
                                {
                                    if (shape.m_datas2[i] > m_candleMaxRight)
                                    {
                                        m_candleMaxRight = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_candleMinRight)
                                    {
                                        m_candleMinRight = shape.m_datas2[i];
                                    }
                                }
                            }
                            else if (shape.m_divIndex == 1)
                            {
                                if (shape.m_leftOrRight)
                                {
                                    if (shape.m_datas2[i] > m_volMax)
                                    {
                                        m_volMax = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_volMin)
                                    {
                                        m_volMin = shape.m_datas2[i];
                                    }
                                }
                                else
                                {
                                    if (shape.m_datas2[i] > m_volMaxRight)
                                    {
                                        m_volMaxRight = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_volMinRight)
                                    {
                                        m_volMinRight = shape.m_datas2[i];
                                    }
                                }
                            }
                            else if (shape.m_divIndex == 2)
                            {
                                if (shape.m_leftOrRight)
                                {
                                    if (shape.m_datas2[i] > m_indMax)
                                    {
                                        m_indMax = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_indMin)
                                    {
                                        m_indMin = shape.m_datas2[i];
                                    }
                                }
                                else
                                {
                                    if (shape.m_datas2[i] > m_indMaxRight)
                                    {
                                        m_indMaxRight = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_indMinRight)
                                    {
                                        m_indMinRight = shape.m_datas2[i];
                                    }
                                }
                            }
                            else if (shape.m_divIndex == 3)
                            {
                                if (shape.m_leftOrRight)
                                {
                                    if (shape.m_datas2[i] > m_indMax2)
                                    {
                                        m_indMax2 = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_indMin2)
                                    {
                                        m_indMin2 = shape.m_datas2[i];
                                    }
                                }
                                else
                                {
                                    if (shape.m_datas2[i] > m_indMax2Right)
                                    {
                                        m_indMax2Right = shape.m_datas2[i];
                                    }
                                    if (shape.m_datas2[i] < m_indMin2Right)
                                    {
                                        m_indMin2Right = shape.m_datas2[i];
                                    }
                                }
                            }
                        }
                    }
                }
            }
            if (isTrend)
            {
                double subMax = Math.Max(Math.Abs(m_candleMax - firstOpen),
                    Math.Abs(m_candleMin - firstOpen));
                m_candleMax = firstOpen + subMax;
                m_candleMin = firstOpen - subMax;
            }
            else
            {
                if (m_candleMax == 0 && m_candleMin == 0)
                {
                    m_candleMax = 1;
                    m_candleMin = -1;
                }
                if (m_volMax == 0 && m_volMin == 0)
                {
                    m_volMax = 1;
                    m_volMin = -1;
                }
                if (m_indMax == 0 && m_indMin == 0)
                {
                    m_indMax = 1;
                    m_indMin = -1;
                }
                if (m_indMax2 == 0 && m_indMin2 == 0)
                {
                    m_indMax2 = 1;
                    m_indMin2 = -1;
                }
                if (m_candleMaxRight == 0 && m_candleMinRight == 0)
                {
                    m_candleMaxRight = 1;
                    m_candleMinRight = -1;
                }
                if (m_volMaxRight == 0 && m_volMinRight == 0)
                {
                    m_volMaxRight = 1;
                    m_volMinRight = -1;
                }
                if (m_indMaxRight == 0 && m_indMinRight == 0)
                {
                    m_indMaxRight = 1;
                    m_indMinRight = -1;
                }
                if (m_indMax2Right == 0 && m_indMin2Right == 0)
                {
                    m_indMax2Right = 1;
                    m_indMin2Right = -1;
                }
            }
        }

        /// <summary>
        /// 检查最后可见索引
        /// </summary>
        public virtual void checkChartLastVisibleIndex()
        {
            int dataCount = m_datas.size();
            int workingAreaWidth = getChartWorkAreaWidth();
            int maxVisibleRecord = getChartMaxVisibleCount(m_hScalePixel, workingAreaWidth);
            if (m_firstVisibleIndex < 0)
            {
                m_firstVisibleIndex = 0;
            }
            if (m_lastVisibleIndex >= m_firstVisibleIndex + maxVisibleRecord - 1 || m_lastVisibleIndex < dataCount - 1)
            {
                m_lastVisibleIndex = m_firstVisibleIndex + maxVisibleRecord - 1;
            }
            if (m_lastVisibleIndex > dataCount - 1)
            {
                m_lastVisibleIndex = dataCount - 1;
            }
            if (m_datas.size() > 0 && m_lastVisibleIndex != -1)
            {
                m_lastVisibleKey = m_datas[m_lastVisibleIndex].m_date;
                if (m_lastVisibleIndex == m_datas.size() - 1)
                {
                    m_lastRecordIsVisible = true;
                }
                else
                {
                    m_lastRecordIsVisible = false;
                }
            }
            else
            {
                m_lastVisibleKey = 0;
                m_lastRecordIsVisible = true;
            }
        }

        /// <summary>
        /// 清除缓存数据方法
        /// </summary>
        public virtual void clearDataArr()
        {
            m_allema12 = new ArrayList<double>();
            m_allema26 = new ArrayList<double>();
            m_alldifarr = new ArrayList<double>();
            m_alldeaarr = new ArrayList<double>();
            m_allmacdarr = new ArrayList<double>();
            m_bollUp = new ArrayList<double>();
            m_bollDown = new ArrayList<double>();
            m_bollMid = new ArrayList<double>();
            m_bias1 = new ArrayList<double>();
            m_bias2 = new ArrayList<double>();
            m_bias3 = new ArrayList<double>();
            m_kdjK = new ArrayList<double>();
            m_kdjD = new ArrayList<double>();
            m_kdjJ = new ArrayList<double>();
            m_rsi1 = new ArrayList<double>();
            m_rsi2 = new ArrayList<double>();
            m_rsi3 = new ArrayList<double>();
            m_roc = new ArrayList<double>();
            m_rocMa = new ArrayList<double>();
            m_wr1 = new ArrayList<double>();
            m_wr2 = new ArrayList<double>();
            m_cci = new ArrayList<double>();
            m_bbi = new ArrayList<double>();
            m_trix = new ArrayList<double>();
            m_trixMa = new ArrayList<double>();
            m_dma1 = new ArrayList<double>();
            m_dma2 = new ArrayList<double>();
            m_ma5 = new ArrayList<double>();
            m_ma10 = new ArrayList<double>();
            m_ma20 = new ArrayList<double>();
            m_ma30 = new ArrayList<double>();
            m_ma120 = new ArrayList<double>();
            m_ma250 = new ArrayList<double>();
        }

        /// <summary>
        /// 获取数据
        /// </summary>
        public virtual void calcChartIndicator()
        {
            clearDataArr();
            ArrayList<double> closeArr = new ArrayList<double>();
            ArrayList<double> highArr = new ArrayList<double>();
            ArrayList<double> lowArr = new ArrayList<double>();
            if (m_datas.size() > 0)
            {
                for (int i = 0; i < m_datas.size(); i++)
                {
                    closeArr.add(m_datas[i].m_close);
                    highArr.add(m_datas[i].m_high);
                    lowArr.add(m_datas[i].m_low);
                }
            }
            m_closeArr = closeArr;
            if (m_mainIndicator == "BOLL")
            {
                getBollData(closeArr, 20, m_bollUp, m_bollMid, m_bollDown);
            }
            else if (m_mainIndicator == "MA")
            {
                m_ma5 = maValue(closeArr, 5);
                m_ma10 = maValue(closeArr, 10);
                m_ma20 = maValue(closeArr, 20);
                m_ma30 = maValue(closeArr, 30);
                m_ma120 = maValue(closeArr, 120);
                m_ma250 = maValue(closeArr, 250);
            }
            if (m_showIndicator == "BIAS" || m_showIndicator2 == "BIAS")
            {
                getBIASData(closeArr, 6, 12, 24, m_bias1, m_bias2, m_bias3);
            }
            if (m_showIndicator == "DMA" || m_showIndicator2 == "DMA")
            {
                getDMAData(closeArr, 10, 50, m_dma1, m_dma2);
            }
            if (m_showIndicator == "BBI" || m_showIndicator2 == "BBI")
            {
                getBBIData(closeArr, 3, 6, 12, 24, m_bbi);
            }
            if (m_showIndicator == "RSI" || m_showIndicator2 == "RSI")
            {
                getRSIData(closeArr, 6, 12, 24, m_rsi1, m_rsi2, m_rsi3);
            }
            if (m_showIndicator == "ROC" || m_showIndicator2 == "ROC")
            {
                getRocData(closeArr, 12, 6, m_roc, m_rocMa);
            }
            if (m_showIndicator == "TRIX" || m_showIndicator2 == "TRIX")
            {
                getTRIXData(closeArr, 9, m_trix, m_trixMa);
            }
            if (m_showIndicator == "KDJ" || m_showIndicator2 == "KDJ")
            {
                getKDJData(
                    highArr, lowArr, closeArr, 9, 3, 3, m_kdjK, m_kdjD, m_kdjJ);
            }
            if (m_showIndicator == "WR" || m_showIndicator2 == "WR")
            {
                getWRData(highArr, lowArr, closeArr, 5, 10, m_wr1, m_wr2);
            }
            if (m_showIndicator == "CCI" || m_showIndicator2 == "CCI")
            {
                getCCIData(highArr, lowArr, closeArr, 14, m_cci);
            }
            if (m_showIndicator == "MACD" || m_showIndicator2 == "MACD")
            {
                //缓存MACD数据
                m_allema12.add(closeArr[0]);
                m_allema26.add(closeArr[0]);
                m_alldeaarr.add(0);
                for (int i = 1; i < closeArr.size(); i++)
                {
                    m_allema12.add(getEMA(12, closeArr[i], m_allema12[i - 1]));
                    m_allema26.add(getEMA(26, closeArr[i], m_allema26[i - 1]));
                }
                m_alldifarr = getDIF(m_allema12, m_allema26);
                for (int i = 1; i < m_alldifarr.size(); i++)
                {
                    m_alldeaarr
                        .add(m_alldeaarr[i - 1] * 8 / 10 + m_alldifarr[i] * 2 / 10);
                }
                m_allmacdarr = getMACD(m_alldifarr, m_alldeaarr);
            }
            calculateChartMaxMin();
        }

        /// <summary>
        /// 绘制线条
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        /// <param name="divIndex">图层</param>
        /// <param name="datas">数据</param>
        /// <param name="color">颜色</param>
        /// <param name="selected">是否选中</param>
        public virtual void drawChartLines(FCPaint paint, FCRect clipRect, int divIndex, ArrayList<double> datas, long color, bool selected)
        {
            ArrayList<FCPoint> drawPoints = new ArrayList<FCPoint>();
            int maxVisibleRecord = getChartMaxVisibleCount(m_hScalePixel, getChartWorkAreaWidth());
            int lastValidIndex = m_lastVisibleIndex;
            if (m_lastValidIndex != -1)
            {
                lastValidIndex = m_lastValidIndex;
            }
            for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
            {
                int x = getChartX(i);
                double value = datas[i];
                int y = getChartY(divIndex, value);
                drawPoints.add(new FCPoint((int)x, (int)y));
                if (selected)
                {
                    int kPInterval = maxVisibleRecord / 30;
                    if (kPInterval < 2)
                    {
                        kPInterval = 3;
                    }
                    if (i % kPInterval == 0)
                    {
                        paint.fillRect(color, (int)(x - 3), (int)(y - 3), (int)(x + 3), (int)(y + 3));
                    }
                }
            }
            paint.drawPolyline(color, (float)m_lineWidthChart, 0, drawPoints.ToArray());
        }

        /// <summary>
        /// 绘制线条到右轴
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        /// <param name="divIndex">图层</param>
        /// <param name="datas">数据</param>
        /// <param name="color">颜色</param>
        /// <param name="selected">是否选中</param>
        public virtual void drawChartLinesInRight(FCPaint paint, FCRect clipRect, int divIndex, ArrayList<double> datas, long color, bool selected)
        {
            ArrayList<FCPoint> drawPoints = new ArrayList<FCPoint>();
            int maxVisibleRecord = getChartMaxVisibleCount(m_hScalePixel, getChartWorkAreaWidth());
            int lastValidIndex = m_lastVisibleIndex;
            if (m_lastValidIndex != -1)
            {
                lastValidIndex = m_lastValidIndex;
            }
            for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
            {
                int x = getChartX(i);
                double value = datas[i];
                int y = getChartYInRight(divIndex, value);
                drawPoints.add(new FCPoint((int)x, (int)y));
                if (selected)
                {
                    int kPInterval = maxVisibleRecord / 30;
                    if (kPInterval < 2)
                    {
                        kPInterval = 3;
                    }
                    if (i % kPInterval == 0)
                    {
                        paint.fillRect(color, (int)(x - 3), (int)(y - 3), (int)(x + 3), (int)(y + 3));
                    }
                }
            }
            paint.drawPolyline(color, (float)m_lineWidthChart, 0, drawPoints.ToArray());
        }

        /// <summary>
        /// 绘制画线工具
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public virtual void drawChartPlot(FCPaint paint, FCRect clipRect)
        {
            FCSize size = getSize();
            int divHeight = getCandleDivHeight();
            paint.setClip(new FCRect(Math.Max(clipRect.left, m_leftVScaleWidth), Math.Max(clipRect.top, 0), Math.Min(clipRect.right, size.cx - m_rightVScaleWidth), Math.Min(clipRect.bottom, divHeight)));
            for (int i = 0; i < m_plots.size(); i++)
            {
                FCPlot plot = m_plots[i];
                int index1 = 0, index2 = 0, index3 = 0;
                int mpx1 = 0, mpy1 = 0, mpx2 = 0, mpy2 = 0, mpx3 = 0, mpy3 = 0;
                if (plot.m_plotType == "LRLine" ||
                    plot.m_plotType == "LRChannel" ||
                    plot.m_plotType == "LRBand")
                {
                    ArrayList<double> list = new ArrayList<double>();
                    index1 = getChartIndexByDate(plot.m_key1);
                    index2 = getChartIndexByDate(plot.m_key2);
                    int minIndex = Math.Min(index1, index2);
                    int maxIndex = Math.Max(index1, index2);
                    for (int j = minIndex; j <= maxIndex; j++)
                    {
                        list.add(m_datas[j].m_close);
                    }
                    linearRegressionEquation(list);
                    plot.m_value1 = m_bChart;
                    plot.m_value2 = m_kChart * (maxIndex - minIndex + 1) + m_bChart;
                }
                else if (plot.m_plotType == "BoxLine" ||
                    plot.m_plotType == "TironeLevels" ||
                    plot.m_plotType == "QuadrantLines")
                {
                    getCandleRange(plot);
                    double nHigh = m_nHighChart, nLow = m_nLowChart;
                    index1 = getChartIndexByDate(plot.m_key1);
                    index2 = getChartIndexByDate(plot.m_key2);
                    plot.m_key1 = getChartDateByIndex(Math.Min(index1, index2));
                    plot.m_key2 = getChartDateByIndex(Math.Max(index1, index2));
                    plot.m_value1 = nHigh;
                    plot.m_value2 = nLow;
                }
                if (plot.m_key1 > 0)
                {
                    index1 = getChartIndexByDate(plot.m_key1);
                    mpx1 = getChartX(index1);
                    mpy1 = getChartY(0, plot.m_value1);
                    if (m_sPlot == plot)
                    {
                        paint.fillEllipse(plot.m_pointColor, (int)(mpx1 - m_plotPointSizeChart), (int)(mpy1 - m_plotPointSizeChart), (int)(mpx1 + m_plotPointSizeChart), (int)(mpy1 + m_plotPointSizeChart));
                    }
                }
                if (plot.m_key2 > 0)
                {
                    index2 = getChartIndexByDate(plot.m_key2);
                    mpx2 = getChartX(index2);
                    mpy2 = getChartY(0, plot.m_value2);
                    if (m_sPlot == plot)
                    {
                        paint.fillEllipse(
                            plot.m_pointColor,
                            (int)(mpx2 - m_plotPointSizeChart),
                            (int)(mpy2 - m_plotPointSizeChart),
                            (int)(mpx2 + m_plotPointSizeChart),
                            (int)(mpy2 + m_plotPointSizeChart));
                    }
                }
                if (plot.m_key3 > 0)
                {
                    index3 = getChartIndexByDate(plot.m_key3);
                    mpx3 = getChartX(index3);
                    mpy3 = getChartY(0, plot.m_value3);
                    if (m_sPlot == plot)
                    {
                        paint.fillEllipse(
                            plot.m_pointColor,
                            (int)(mpx3 - m_plotPointSizeChart),
                            (int)(mpy3 - m_plotPointSizeChart),
                            (int)(mpx3 + m_plotPointSizeChart),
                            (int)(mpy3 + m_plotPointSizeChart));
                    }
                }
                if (plot.m_plotType == "Line")
                {
                    lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                    if (mpx2 == mpx1)
                    {
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, mpx1, 0, mpx1, divHeight);
                    }
                    else
                    {
                        double newX1 = m_leftVScaleWidth;
                        double newY1 = newX1 * m_kChart + m_bChart;
                        double newX2 = size.cx - m_rightVScaleWidth;
                        double newY2 = newX2 * m_kChart + m_bChart;
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)newX1, (int)newY1, (int)newX2, (int)newY2);
                    }
                }
                else if (plot.m_plotType == "ArrowSegment")
                {
                    int arrowSize = 24;
                    double slopy = 0, cosy = 0, siny = 0;
                    slopy = Math.Atan2(mpy1 - mpy2, mpx1 - mpx2);
                    cosy = Math.Cos(slopy);
                    siny = Math.Sin(slopy);
                    FCPoint ptPoint = new FCPoint(0, 0);
                    ptPoint.x = mpx2;
                    ptPoint.y = mpy2;
                    ArrayList<FCPoint> pts = new ArrayList<FCPoint>();
                    pts.add(new FCPoint(0, 0));
                    pts.add(new FCPoint(0, 0));
                    pts.add(new FCPoint(0, 0));
                    pts[0] = ptPoint;
                    pts[1] = new FCPoint((int)(ptPoint.x + (arrowSize * cosy - (arrowSize / 2.0 * siny) + 0.5)), (int)(ptPoint.y + (arrowSize * siny + (arrowSize / 2.0 * cosy) + 0.5)));
                    pts[2] = new FCPoint((int)(ptPoint.x + (arrowSize * cosy + arrowSize / 2.0 * siny + 0.5)), (int)(ptPoint.y - (arrowSize / 2.0 * cosy - arrowSize * siny + 0.5)));
                    arrowSize = 20;
                    FCPoint ptPoint2 = new FCPoint(0, 0);
                    ptPoint2.x = mpx2;
                    ptPoint2.y = mpy2;
                    ArrayList<FCPoint> pts2 = new ArrayList<FCPoint>();
                    pts2.add(new FCPoint(0, 0));
                    pts2.add(new FCPoint(0, 0));
                    pts2.add(new FCPoint(0, 0));
                    pts2[0] = ptPoint2;
                    pts2[1] = new FCPoint((int)(ptPoint2.x + (arrowSize * cosy - (arrowSize / 2.0 * siny) + 0.5)), (int)(ptPoint2.y + (arrowSize * siny + (arrowSize / 2.0 * cosy) + 0.5)));
                    pts2[2] = new FCPoint((int)(ptPoint2.x + (arrowSize * cosy + arrowSize / 2.0 * siny + 0.5)), (int)(ptPoint2.y - (arrowSize / 2.0 * cosy - arrowSize * siny + 0.5)));
                    lineXY(pts2[1].x, pts2[1].y, pts2[2].x, pts2[2].y, 0, 0);
                    double newX1 = 0, newY1 = 0, newX2 = 0, newY2 = 0;
                    if (pts2[1].x > pts2[2].x)
                    {
                        newX1 = pts2[2].x + (pts2[1].x - pts2[2].x) / 3;
                        newX2 = pts2[2].x + (pts2[1].x - pts2[2].x) * 2 / 3;
                    }
                    else
                    {
                        newX1 = pts2[1].x + (pts2[2].x - pts2[1].x) / 3;
                        newX2 = pts2[1].x + (pts2[2].x - pts2[1].x) * 2 / 3;
                    }
                    if (m_kChart == 0 && m_bChart == 0)
                    {
                        if (pts2[1].y > pts2[2].y)
                        {
                            newY1 = pts2[2].y + (pts2[1].y - pts2[2].y) / 3;
                            newY2 = pts2[2].y + (pts2[1].y - pts2[2].y) * 2 / 3;
                        }
                        else
                        {
                            newY1 = pts2[1].y + (pts2[2].y - pts2[1].y) / 3;
                            newY2 = pts2[1].y + (pts2[2].y - pts2[1].y) * 2 / 3;
                        }
                    }
                    else
                    {
                        newY1 = (m_kChart * newX1) + m_bChart;
                        newY2 = (m_kChart * newX2) + m_bChart;
                    }
                    pts2[1] = new FCPoint((int)newX1, (int)newY1);
                    pts2[2] = new FCPoint((int)newX2, (int)newY2);
                    ArrayList<FCPoint> drawPoints = new ArrayList<FCPoint>();
                    drawPoints.add(new FCPoint(0, 0));
                    drawPoints.add(new FCPoint(0, 0));
                    drawPoints.add(new FCPoint(0, 0));
                    drawPoints.add(new FCPoint(0, 0));
                    drawPoints.add(new FCPoint(0, 0));
                    drawPoints.add(new FCPoint(0, 0));
                    drawPoints[0] = new FCPoint(ptPoint.x, ptPoint.y);
                    drawPoints[1] = new FCPoint(pts[1].x, pts[1].y);
                    if (mpy1 >= mpy2)
                    {
                        drawPoints[2] = new FCPoint(pts2[1].x, pts2[1].y);
                    }
                    else
                    {
                        drawPoints[2] = new FCPoint(pts2[2].x, pts2[2].y);
                    }
                    drawPoints[3] = new FCPoint(mpx1, mpy1);
                    if (mpy1 >= mpy2)
                    {
                        drawPoints[4] = new FCPoint(pts2[2].x, pts2[2].y);
                    }
                    else
                    {
                        drawPoints[4] = new FCPoint(pts2[1].x, pts2[1].y);
                    }
                    drawPoints[5] = new FCPoint(pts[2].x, pts[2].y);

                    paint.fillPolygon(plot.m_lineColor, drawPoints.ToArray());
                }
                else if (plot.m_plotType == "AngleLine")
                {
                    lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                    if (mpx2 == mpx1)
                    {
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, mpx1, 0, mpx1, divHeight);
                    }
                    else
                    {
                        double newX1 = m_leftVScaleWidth;
                        double newY1 = newX1 * m_kChart + m_bChart;
                        double newX2 = size.cx - m_rightVScaleWidth;
                        double newY2 = newX2 * m_kChart + m_bChart;
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)newX1, (int)newY1, (int)newX2, (int)newY2);
                    }
                    lineXY(mpx1, mpy1, mpx3, mpy3, 0, 0);
                    if (mpx3 == mpx1)
                    {
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, mpx1, 0, mpx1, divHeight);
                    }
                    else
                    {
                        double newX1 = m_leftVScaleWidth;
                        double newY1 = newX1 * m_kChart + m_bChart;
                        double newX2 = size.cx - m_rightVScaleWidth;
                        double newY2 = newX2 * m_kChart + m_bChart;
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)newX1, (int)newY1, (int)newX2, (int)newY2);
                    }
                }
                else if (plot.m_plotType == "Parallel")
                {
                    lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                    if (mpx2 == mpx1)
                    {
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, mpx1, 0, mpx1, divHeight);
                    }
                    else
                    {
                        double newX1 = m_leftVScaleWidth;
                        double newY1 = newX1 * m_kChart + m_bChart;
                        double newX2 = size.cx - m_rightVScaleWidth;
                        double newY2 = newX2 * m_kChart + m_bChart;
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)newX1, (int)newY1, (int)newX2, (int)newY2);
                    }
                    double newB = mpy3 - m_kChart * mpx3;
                    if (mpx2 == mpx1)
                    {
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, mpx3, 0, mpx3, divHeight);
                    }
                    else
                    {
                        double newX1 = m_leftVScaleWidth;
                        double newY1 = newX1 * m_kChart + newB;
                        double newX2 = size.cx - m_rightVScaleWidth;
                        double newY2 = newX2 * m_kChart + newB;
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)newX1, (int)newY1, (int)newX2, (int)newY2);
                    }
                }
                else if (plot.m_plotType == "Percent")
                {
                    ArrayList<int> list = getPercentParams(mpy1, mpy2);
                    ArrayList<String> texts = new ArrayList<string>();
                    texts.add("0%");
                    texts.add("25%");
                    texts.add("50%");
                    texts.add("75%");
                    texts.add("100%");
                    for (int j = 0; j < list.size(); j++)
                    {
                        paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, m_leftVScaleWidth,
                            list[j], size.cx - m_rightVScaleWidth, list[j]);
                        FCSize tSize = paint.textSize(texts[j], getFont());
                        paint.drawText(texts[j], getTextColor(), getFont(),
                            new FCRect(m_leftVScaleWidth + 5, list[j] - tSize.cy - 2, m_leftVScaleWidth + 5 + tSize.cx, list[j] - 2));
                    }
                }
                else if (plot.m_plotType == "FiboTimezone")
                {
                    int fValue = 1;
                    int aIndex = index1;
                    int pos = 1;
                    paint.drawLine(
                        plot.m_lineColor, plot.m_lineWidth, 0, mpx1, 0, mpx1, divHeight);
                    FCSize tSize = paint.textSize("1", getFont());
                    paint.drawText(
                        "1", getTextColor(), getFont(), new FCRect(mpx1, divHeight - tSize.cy, mpx1 + tSize.cx, divHeight));
                    while (aIndex + fValue <= m_lastVisibleIndex)
                    {
                        fValue = fibonacciValue(pos);
                        int newIndex = aIndex + fValue;
                        double newX = getChartX(newIndex);
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)newX, 0, (int)newX, divHeight);
                        FCSize tSize2 = paint.textSize(FCTran.doubleToStr(fValue), getFont());
                        paint.drawText(FCTran.doubleToStr(fValue), getTextColor(), getFont(), new FCRect((int)newX,
                            divHeight - tSize2.cy, (int)newX + tSize2.cx, divHeight));
                        pos++;
                    }
                }
                else if (plot.m_plotType == "SpeedResist")
                {
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                    if (mpx1 != mpx2 && mpy1 != mpy2)
                    {
                        FCPoint firstP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) / 3);
                        FCPoint secondP = new FCPoint(mpx2, mpy2 - (mpy2 - mpy1) * 2 / 3);
                        FCPoint startP = new FCPoint(mpx1, mpy1);
                        double fK = 0, fB = 0, sK = 0, sB = 0;
                        lineXY(startP.x, startP.y, firstP.x, firstP.y, 0, 0);
                        fK = m_kChart;
                        fB = m_bChart;
                        lineXY(startP.x, startP.y, secondP.x, secondP.y, 0, 0);
                        sK = m_kChart;
                        sB = m_bChart;
                        double newYF = 0, newYS = 0;
                        double newX = 0;
                        if (mpx2 > mpx1)
                        {
                            newYF = fK * (size.cx - m_rightVScaleWidth) + fB;
                            newYS = sK * (size.cx - m_rightVScaleWidth) + sB;
                            newX = (size.cx - m_rightVScaleWidth);
                        }
                        else
                        {
                            newYF = fB;
                            newYS = sB;
                            newX = m_leftVScaleWidth;
                        }
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, startP.x, startP.y, (int)newX, (int)newYF);
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, startP.x, startP.y, (int)newX, (int)newYS);
                    }
                }
                else if (plot.m_plotType == "FiboFanline")
                {
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                    if (mpx1 != mpx2 && mpy1 != mpy2)
                    {
                        FCPoint firstP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) * 0.382));
                        FCPoint secondP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) * 0.5));
                        FCPoint thirdP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) * 0.618));
                        FCPoint startP = new FCPoint((int)mpx1, (int)mpy1);
                        ArrayList<FCPoint> listP = new ArrayList<FCPoint>();
                        listP.add(firstP);
                        listP.add(secondP);
                        listP.add(thirdP);
                        int listSize = listP.size();
                        for (int j = 0; j < listSize; j++)
                        {
                            //获取直线参数
                            lineXY(startP.x, startP.y, listP[j].x, listP[j].y, 0, 0);
                            double newX = 0;
                            double newY = 0;
                            if (mpx2 > mpx1)
                            {
                                newY = m_kChart * (size.cx - m_rightVScaleWidth) +
                                    m_bChart;
                                newX = (size.cx - m_rightVScaleWidth);
                            }
                            else
                            {
                                newY = m_bChart;
                                newX = m_leftVScaleWidth;
                            }
                            paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, startP.x, startP.y,
                                (int)newX, (int)newY);
                        }
                    }
                }
                else if (plot.m_plotType == "LRLine")
                {
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                }
                else if (plot.m_plotType == "LRBand")
                {
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                    getLRBandRange(plot, m_kChart, m_bChart);
                    mpy1 = getChartY(0, plot.m_value1 + m_upSubValue);
                    mpy2 = getChartY(0, plot.m_value2 + m_upSubValue);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                    mpy1 = getChartY(0, plot.m_value1 - m_downSubValue);
                    mpy2 = getChartY(0, plot.m_value2 - m_downSubValue);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                }
                else if (plot.m_plotType == "LRChannel")
                {
                    getLRBandRange(plot, m_kChart, m_bChart);
                    lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                    double rightX = size.cx - m_rightVScaleWidth;
                    double rightY = rightX * m_kChart + m_bChart;
                    paint.drawLine(
                        plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, (int)rightX, (int)rightY);
                    mpy1 = getChartY(0, plot.m_value1 + m_upSubValue);
                    mpy2 = getChartY(0, plot.m_value2 + m_upSubValue);
                    lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                    rightY = rightX * m_kChart + m_bChart;
                    paint.drawLine(
                        plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, (int)rightX, (int)rightY);
                    mpy1 = getChartY(0, plot.m_value1 - m_downSubValue);
                    mpy2 = getChartY(0, plot.m_value2 - m_downSubValue);
                    lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                    rightY = rightX * m_kChart + m_bChart;
                    paint.drawLine(
                        plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, (int)rightX, (int)rightY);
                }
                else if (plot.m_plotType == "Segment")
                {
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                }
                else if (plot.m_plotType == "Ray")
                {
                    lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                    if (m_kChart != 0 || m_bChart != 0)
                    {
                        double leftX = m_leftVScaleWidth;
                        double leftY = leftX * m_kChart + m_bChart;
                        double rightX = size.cx - m_rightVScaleWidth;
                        double rightY = rightX * m_kChart + m_bChart;
                        if (mpx1 >= mpx2)
                        {
                            paint.drawLine(
                                plot.m_lineColor, plot.m_lineWidth, 0, (int)leftX, (int)leftY, mpx1, mpy1);
                        }
                        else
                        {
                            paint.drawLine(
                                plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, (int)rightX, (int)rightY);
                        }
                    }
                    //垂直时
                    else
                    {
                        if (mpy1 >= mpy2)
                        {
                            paint.drawLine(
                                plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx1, 0);
                        }
                        else
                        {
                            paint.drawLine(
                                plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx1, divHeight);
                        }
                    }
                }
                else if (plot.m_plotType == "Triangle")
                {
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx2, mpy2, mpx3, mpy3);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx3, mpy3);
                }
                else if (plot.m_plotType == "SymmetricTriangle")
                {
                    if (mpx2 != mpx1)
                    {
                        double a = (double)(mpy2 - mpy1) / (double)(mpx2 - mpx1);
                        double b = mpy1 - a * mpx1;
                        double c = -a;
                        double d = mpy3 - c * mpx3;
                        double leftX = m_leftVScaleWidth;
                        double leftY = leftX * a + b;
                        double rightX = size.cx - m_rightVScaleWidth;
                        double rightY = rightX * a + b;
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)leftX, (int)leftY, (int)rightX, (int)rightY);
                        leftY = leftX * c + d;
                        rightY = rightX * c + d;
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, (int)leftX, (int)leftY, (int)rightX, (int)rightY);
                    }
                    else
                    {
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, mpx1, 0, mpx1, divHeight);
                        paint.drawLine(
                            plot.m_lineColor, plot.m_lineWidth, 0, mpx3, 0, mpx3, divHeight);
                    }
                }
                else if (plot.m_plotType == "Rect")
                {
                    int sX1 = Math.Min(mpx1, mpx2);
                    int sY1 = Math.Min(mpy1, mpy2);
                    int sX2 = Math.Max(mpx1, mpx2);
                    int sY2 = Math.Max(mpy1, mpy2);
                    paint.drawRect(plot.m_lineColor, plot.m_lineWidth, 0, sX1, sY1, sX2, sY2);
                }
                else if (plot.m_plotType == "Cycle")
                {
                    int r = (int)Math.Sqrt(
                        (Math.Abs((mpx2 - mpx1) * (mpx2 - mpx1) + (mpy2 - mpy1) * (mpy2 - mpy1))));
                    paint.drawEllipse(plot.m_lineColor, plot.m_lineWidth, 0, mpx1 - r, mpy1 - r,
                        mpx1 + r, mpy1 + r);
                }
                else if (plot.m_plotType == "CircumCycle")
                {
                    ellipseOR(mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
                    paint.drawEllipse(
                        plot.m_lineColor,
                        plot.m_lineWidth,
                        0,
                        (int)(m_oXChart - m_rChart),
                        (int)(m_oYChart - m_rChart),
                        (int)(m_oXChart + m_rChart),
                        (int)(m_oYChart + m_rChart));
                }
                else if (plot.m_plotType == "Ellipse")
                {
                    double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
                    if (mpx1 <= mpx2)
                    {
                        x1 = mpx2;
                        y1 = mpy2;
                        x2 = mpx1;
                        y2 = mpy1;
                    }
                    else
                    {
                        x1 = mpx1;
                        y1 = mpy1;
                        x2 = mpx2;
                        y2 = mpy2;
                    }
                    double x = x1 - (x1 - x2);
                    double y = 0;
                    double width = (x1 - x2) * 2;
                    double height = 0;
                    if (y1 >= y2)
                    {
                        height = (y1 - y2) * 2;
                    }
                    else
                    {
                        height = (y2 - y1) * 2;
                    }
                    y = y2 - height / 2;
                    paint.drawEllipse(
                        plot.m_lineColor, plot.m_lineWidth, 0, (int)x, (int)y, (int)(x + width), (int)(y + height));
                }
                else if (plot.m_plotType == "ParalleGram")
                {
                    parallelogram(mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx1, mpy1, mpx2, mpy2);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx2, mpy2, mpx3, mpy3);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, mpx3, mpy3,
                        (int)m_x4Chart, (int)m_y4Chart);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, (int)m_x4Chart,
                        (int)m_y4Chart, mpx1, mpy1);
                }
                else if (plot.m_plotType == "BoxLine")
                {
                    int sX1 = Math.Min(mpx1, mpx2);
                    int sY1 = Math.Min(mpy1, mpy2);
                    int sX2 = Math.Max(mpx1, mpx2);
                    int sY2 = Math.Max(mpy1, mpy2);
                    paint.drawRect(plot.m_lineColor, plot.m_lineWidth, 0, sX1, sY1, sX2, sY2);
                    String bText = FCTran.intToStr(Math.Abs(index2 - index1) + 1);
                    FCSize tSize = paint.textSize(bText, getFont());
                    paint.drawText(FCTran.intToStr(Math.Abs(index2 - index1) + 1), getTextColor(),
                        getFont(), new FCRect(sX1 + 2, sY1 + 2, sX1 + 2 + tSize.cx, sY1 + 2 + tSize.cy));
                    ArrayList<double> closeList = new ArrayList<double>();
                    for (int j = index1; j <= index2; j++)
                    {
                        closeList.add(m_datas[j].m_close);
                    }
                    double avgClose = avgValue(closeList);
                    int closeY = getChartY(0, avgClose);
                    paint.drawLine(
                        plot.m_lineColor, plot.m_lineWidth, 0, sX1, closeY, sX2, closeY);
                    String drawAvg = FCTran.getValueByDigit(avgClose, m_candleDigit);
                    tSize = paint.textSize(drawAvg, getFont());
                    paint.drawText(
                        drawAvg, getTextColor(), getFont(), new FCRect(sX1 + 2, closeY - tSize.cy - 2, sX1 + 2 + tSize.cx, closeY - 2));
                }
                else if (plot.m_plotType == "TironeLevels")
                {
                    int sX1 = Math.Min(mpx1, mpx2);
                    int sY1 = Math.Min(mpy1, mpy2);
                    int sX2 = Math.Max(mpx1, mpx2);
                    int sY2 = Math.Max(mpy1, mpy2);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, sX1, sY1, sX2, sY1);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, sX1, sY2, sX2, sY2);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, sX1 + (sX2 - sX1) / 2,
                        sY1, sX1 + (sX2 - sX1) / 2, sY2);
                    double t2 = m_nHighChart - (m_nHighChart - m_nLowChart) / 3,
                        t3 = m_nHighChart - (m_nHighChart - m_nLowChart) / 2,
                        t4 = m_nHighChart - 2 * (m_nHighChart - m_nLowChart) / 3;
                    ArrayList<double> tList = new ArrayList<double>();
                    tList.add(t2);
                    tList.add(t3);
                    tList.add(t4);
                    for (int j = 0; j < tList.size(); j++)
                    {
                        int y = getChartY(0, tList[j]);
                        //画直线
                        paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, m_leftVScaleWidth,
                            y, size.cx - m_rightVScaleWidth, y);
                        String str = FCTran.getValueByDigit(tList[j], m_candleDigit);
                        FCSize tSize = paint.textSize(str, getFont());
                        paint.drawText(str, getTextColor(), getFont(),
                            new FCRect(m_leftVScaleWidth + 2, y - tSize.cy - 2, m_leftVScaleWidth + 2 + tSize.cx, y - 2));
                    }
                }
                else if (plot.m_plotType == "QuadrantLines")
                {
                    int sX1 = Math.Min(mpx1, mpx2);
                    int sY1 = Math.Min(mpy1, mpy2);
                    int sX2 = Math.Max(mpx1, mpx2);
                    int sY2 = Math.Max(mpy1, mpy2);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, sX1, sY1, sX2, sY1);
                    paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, sX1, sY2, sX2, sY2);
                    double t2 = m_nHighChart - (m_nHighChart - m_nLowChart) / 4,
                        t3 = m_nHighChart - (m_nHighChart - m_nLowChart) / 2,
                        t4 = m_nHighChart - 3 * (m_nHighChart - m_nLowChart) / 4;
                    ArrayList<double> tList = new ArrayList<double>();
                    tList.add(t2);
                    tList.add(t3);
                    tList.add(t4);
                    for (int j = 0; j < tList.size(); j++)
                    {
                        int y = getChartY(0, tList[j]);
                        //画直线
                        paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, sX1, y, sX2, y);
                    }
                }
                else if (plot.m_plotType == "GoldenRatio")
                {
                    double sY1 = Math.Min(mpy1, mpy2);
                    double sY2 = Math.Max(mpy1, mpy2);
                    ArrayList<double> ranges = new ArrayList<double>();
                    ranges.add(0);
                    ranges.add(0.236);
                    ranges.add(0.382);
                    ranges.add(0.5);
                    ranges.add(0.618);
                    ranges.add(0.809);
                    ranges.add(1);
                    ranges.add(1.382);
                    ranges.add(1.618);
                    ranges.add(2);
                    ranges.add(2.382);
                    ranges.add(2.618);
                    for (int j = 0; j < ranges.size(); j++)
                    {
                        double newY = sY1 <= sY2
                            ? sY1 + (sY2 - sY1) * ranges[j]
                            : sY2 + (sY1 - sY2) * (1 - ranges[j]);
                        paint.drawLine(plot.m_lineColor, plot.m_lineWidth, 0, m_leftVScaleWidth,
                            (int)newY, size.cx - m_rightVScaleWidth, (int)newY);
                        FCPoint newPoint = new FCPoint(0, (int)newY);
                        double value = getCandleDivValue(newPoint);
                        String str = FCTran.getValueByDigit(value, m_candleDigit);
                        FCSize tSize = paint.textSize(str, getFont());
                        paint.drawText(str, getTextColor(), getFont(),
                            new FCRect(m_leftVScaleWidth + 2, (int)newY - tSize.cy - 2, m_leftVScaleWidth + 2 + tSize.cx, (int)newY - 2));
                    }
                }
            }
            paint.setClip(clipRect);
        }

        /// <summary>
        /// 绘制图表
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public virtual void drawChartStock(FCPaint paint, FCRect clipRect)
        {
            int candleHeight = getCandleDivHeight();
            int volHeight = getVolDivHeight();
            int indHeight = getIndDivHeight();
            int indHeight2 = getIndDivHeight2();
            FCSize size = getSize();
            bool isTrend = m_cycle == "trend";
            int cWidth = (int)((m_hScalePixel - 3) / 2);
            if (cWidth < 0)
            {
                cWidth = 0;
            }
            int lastValidIndex = m_lastVisibleIndex;
            if (m_lastValidIndex != -1)
            {
                lastValidIndex = m_lastValidIndex;
            }
            if (m_datas.size() > 0)
            {
                int maxVisibleRecord = getChartMaxVisibleCount(m_hScalePixel, getChartWorkAreaWidth());
                paint.setClip(new FCRect(Math.Max(clipRect.left, m_leftVScaleWidth), Math.Max(clipRect.top, 0), Math.Min(clipRect.right, size.cx - m_rightVScaleWidth), Math.Min(clipRect.bottom, candleHeight)));
                if (isTrend)
                {
                    FCPoint[] points = new FCPoint[lastValidIndex - m_firstVisibleIndex + 1];
                    for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
                    {
                        int x = getChartX(i);
                        double close = m_datas[i].m_close;
                        int closeY = getChartY(0, close);
                        points[i - m_firstVisibleIndex] = new FCPoint(x, closeY);
                    }
                    paint.drawPolyline(m_trendColor, m_lineWidthChart, 0, points);
                }
                else
                {
                    bool hasMinTag = false, hasMaxTag = false;
                    for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
                    {
                        int x = getChartX(i);
                        double open = m_datas[i].m_open;
                        double close = m_datas[i].m_close;
                        double high = m_datas[i].m_high;
                        double low = m_datas[i].m_low;
                        int openY = getChartY(0, open);
                        int closeY = getChartY(0, close);
                        int highY = getChartY(0, high);
                        int lowY = getChartY(0, low);
                        if (close >= open)
                        {
                            if (close == open && m_midColor != FCColor.None)
                            {
                                paint.drawLine(
                                    m_midColor, m_lineWidthChart, 0, x, highY, x, lowY);
                            }
                            else
                            {
                                paint.drawLine(
                                    m_upColor, m_lineWidthChart, 0, x, highY, x, lowY);
                            }
                            if (cWidth > 0)
                            {
                                if (close == open)
                                {
                                    if (m_midColor != FCColor.None)
                                    {
                                        paint.drawLine(m_midColor, m_lineWidthChart, 0, x - cWidth,
                                            closeY, x + cWidth, closeY);
                                    }
                                    else
                                    {
                                        paint.drawLine(m_upColor, m_lineWidthChart, 0, x - cWidth,
                                            closeY, x + cWidth, closeY);
                                    }
                                }
                                else
                                {
                                    if (m_candleStyle == "rect2")
                                    {
                                        paint.fillRect(
                                            m_backColor, x - cWidth, closeY, x + cWidth, openY);
                                        paint.drawRect(m_upColor, 1, 0, x - cWidth, closeY, x + cWidth + 1, openY);
                                    }
                                    else
                                    {
                                        paint.fillRect(
                                            m_upColor, x - cWidth, closeY, x + cWidth, openY);
                                    }
                                }
                            }
                        }
                        else
                        {
                            paint.drawLine(
                                    m_downColor, m_lineWidthChart, 0, x, highY, x, lowY);
                            if (cWidth > 0)
                            {
                                paint.fillRect(
                                    m_downColor, x - cWidth, openY, x + cWidth, closeY);
                            }
                        }
                        if (m_selectShape == "CANDLE")
                        {
                            int kPInterval = maxVisibleRecord / 30;
                            if (kPInterval < 2)
                            {
                                kPInterval = 3;
                            }
                            if (i % kPInterval == 0)
                            {
                                paint.fillRect(
                                        m_indicatorColors[0], x - 3, closeY - 3, x + 3, closeY + 3);
                            }
                        }
                        if (!hasMaxTag)
                        {
                            if (high == m_candleMax)
                            {
                                String tag = FCTran.getValueByDigit(high, m_candleDigit);
                                FCSize tSize = paint.textSize(tag, getFont());
                                paint.drawText(tag, getTextColor(), getFont(), new FCRect(x - tSize.cx / 2,
                                    highY - tSize.cy / 2 - 2, x + tSize.cx / 2, highY + tSize.cy / 2 - 2));
                                hasMaxTag = true;
                            }
                        }
                        if (!hasMinTag)
                        {
                            if (low == m_candleMin)
                            {
                                String tag = FCTran.getValueByDigit(low, m_candleDigit);
                                FCSize tSize = paint.textSize(tag, getFont());
                                paint.drawText(tag, getTextColor(), getFont(), new FCRect(x - tSize.cx / 2,
                                    lowY + 2 + tSize.cy / 2, x + tSize.cx / 2,
                                    lowY + 2 + tSize.cy * 3 / 2));
                                hasMinTag = true;
                            }
                        }
                    }
                }
                paint.setClip(clipRect);
                if (volHeight > 0)
                {
                    for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
                    {
                        int x = getChartX(i);
                        double open = m_datas[i].m_open;
                        double close = m_datas[i].m_close;
                        double volume = m_datas[i].m_volume;
                        int volY = getChartY(1, volume);
                        int zeroY = getChartY(1, 0);
                        if (close >= open)
                        {
                            if (isTrend)
                            {
                                paint.drawLine(m_upColor, m_lineWidthChart, 0, x,
                                        volY, x, zeroY);
                            }
                            else
                            {
                                if (cWidth > 0)
                                {
                                    if (m_barStyle == "rect2")
                                    {
                                        paint.fillRect(
                                            m_backColor, x - cWidth, volY, x + cWidth, zeroY);
                                        paint.drawRect(m_upColor, 1, 0, x - cWidth, volY, x + cWidth + 1, zeroY);
                                    }
                                    else
                                    {
                                        paint.fillRect(
                                            m_upColor, x - cWidth, volY, x + cWidth, zeroY);
                                    }
                                }
                                else
                                {
                                    paint.drawLine(m_upColor, m_lineWidthChart, 0, x - cWidth,
                                            volY, x + cWidth, zeroY);
                                }
                            }
                        }
                        else
                        {
                            if (isTrend)
                            {
                                paint.drawLine(m_downColor, m_lineWidthChart, 0, x,
                                        volY, x, zeroY);
                            }
                            else
                            {
                                if (cWidth > 0)
                                {
                                    paint.fillRect(
                                            m_downColor, x - cWidth, volY, x + cWidth, zeroY);
                                }
                                else
                                {
                                    paint.drawLine(m_downColor, m_lineWidthChart, 0,
                                            x - cWidth, volY, x + cWidth, zeroY);
                                }
                            }
                        }
                        if (m_selectShape == "VOL")
                        {
                            int kPInterval = maxVisibleRecord / 30;
                            if (kPInterval < 2)
                            {
                                kPInterval = 3;
                            }
                            if (i % kPInterval == 0)
                            {
                                paint.fillRect(
                                    m_indicatorColors[0], x - 3, volY - 3, x + 3, volY + 3);
                            }
                        }
                    }
                }
                if (!isTrend)
                {
                    paint.setClip(new FCRect(Math.Max(clipRect.left, m_leftVScaleWidth), Math.Max(clipRect.top, 0), Math.Min(clipRect.right, size.cx - m_rightVScaleWidth), Math.Min(clipRect.bottom, candleHeight)));
                    if (m_mainIndicator == "BOLL")
                    {
                        drawChartLines(paint, clipRect, 0,
                            m_bollMid, m_indicatorColors[0],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "MID") ? true : false);
                        drawChartLines(paint, clipRect, 0,
                            m_bollUp, m_indicatorColors[1],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "UP") ? true : false);
                        drawChartLines(paint, clipRect, 0,
                            m_bollDown, m_indicatorColors[2],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "DOWN") ? true : false);
                    }
                    else if (m_mainIndicator == "MA")
                    {
                        drawChartLines(paint, clipRect, 0,
                            m_ma5, m_indicatorColors[0],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "5") ? true : false);
                        drawChartLines(paint, clipRect, 0,
                            m_ma10, m_indicatorColors[1],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "10") ? true : false);
                        drawChartLines(paint, clipRect, 0,
                            m_ma20, m_indicatorColors[2],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "20") ? true : false);
                        drawChartLines(paint, clipRect, 0,
                            m_ma30, m_indicatorColors[5],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "30") ? true : false);
                        drawChartLines(paint, clipRect, 0,
                            m_ma120, m_indicatorColors[4],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "120") ? true : false);
                        drawChartLines(paint, clipRect, 0,
                            m_ma250, m_indicatorColors[3],
                            (m_selectShape == m_mainIndicator &&
                                    m_selectShapeEx == "250") ? true : false);
                    }
                    paint.setClip(clipRect);
                }
                if (indHeight > 0 || indHeight2 > 0)
                {
                    for (int d = 2; d <= 3; d++)
                    {
                        String sind = m_showIndicator;
                        if (d == 3)
                        {
                            sind = m_showIndicator2;
                            if (indHeight2 <= 0)
                            {
                                continue;
                            }
                        }
                        else
                        {
                            if (indHeight <= 0)
                            {
                                continue;
                            }
                        }
                        if (sind == "MACD")
                        {
                            int zeroY = getChartY(d, 0);
                            paint.drawLine(m_indicatorColors[4], m_lineWidthChart, 0,
                                m_leftVScaleWidth, zeroY, getChartX(m_lastVisibleIndex), zeroY);
                            for (int i = m_firstVisibleIndex; i <= lastValidIndex; i++)
                            {
                                int x = getChartX(i);
                                double macd = m_allmacdarr[i];
                                int macdY = getChartY(d, macd);
                                if (macdY < zeroY)
                                {
                                    paint.drawLine(m_indicatorColors[3], m_lineWidthChart, 0, x,
                                        macdY, x, zeroY);
                                }
                                else
                                {
                                    paint.drawLine(m_indicatorColors[4], m_lineWidthChart, 0, x,
                                        macdY, x, zeroY);
                                }
                                if (m_selectShape == sind &&
                                    m_selectShapeEx == "MACD")
                                {
                                    int kPInterval = maxVisibleRecord / 30;
                                    if (kPInterval < 2)
                                    {
                                        kPInterval = 3;
                                    }
                                    if (i % kPInterval == 0)
                                    {
                                        paint.fillRect(
                                            m_indicatorColors[4], x - 3, macdY - 3, x + 3, macdY + 3);
                                    }
                                }
                            }
                            drawChartLines(paint, clipRect, d,
                                m_alldifarr, m_indicatorColors[0],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "DIF") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_alldeaarr, m_indicatorColors[1],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "DEA") ? true : false);
                        }
                        else if (sind == "KDJ")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_kdjK, m_indicatorColors[0],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "K") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_kdjD, m_indicatorColors[1],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "D") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_kdjJ, m_indicatorColors[2],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "J") ? true : false);
                        }
                        else if (sind == "RSI")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_rsi1, m_indicatorColors[5],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "6") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_rsi2, m_indicatorColors[1],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "12") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_rsi3, m_indicatorColors[2],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "24") ? true : false);
                        }
                        else if (sind == "BIAS")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_bias1, m_indicatorColors[5],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "1") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_bias2, m_indicatorColors[1],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "2") ? true : false);
                            drawChartLines(
                                paint, clipRect, d, m_bias3,
                                m_indicatorColors[2],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "3") ? true : false);
                        }
                        else if (sind == "ROC")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_roc, m_indicatorColors[0],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "ROC") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_rocMa, m_indicatorColors[1],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "ROCMA") ? true : false);
                        }
                        else if (sind == "WR")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_wr1, m_indicatorColors[0],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "1") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_wr2, m_indicatorColors[1],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "2") ? true : false);
                        }
                        else if (sind == "CCI")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_cci, m_indicatorColors[0],
                                (m_selectShape == sind) ? true : false);
                        }
                        else if (sind == "BBI")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_bbi, m_indicatorColors[0],
                                (m_selectShape == sind) ? true : false);
                        }
                        else if (sind == "TRIX")
                        {
                            drawChartLines(paint, clipRect, d,
                                m_trix, m_indicatorColors[0],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "TRIX") ? true : false);
                            drawChartLines(paint, clipRect, d,
                                m_trixMa, m_indicatorColors[1],
                                (m_selectShape == sind &&
                                        m_selectShapeEx == "TRIXMA") ? true : false);
                        }
                        else if (sind == "DMA")
                        {
                            drawChartLines(paint, clipRect, d, m_dma1, m_indicatorColors[0],
                                (m_selectShape == sind && m_selectShapeEx == "DIF") ? true : false);
                            drawChartLines(paint, clipRect, d, m_dma2, m_indicatorColors[1],
                                (m_selectShape == sind && m_selectShapeEx == "DIFMA") ? true : false);
                        }
                    }
                }
            }
            //绘制扩展线条
            if (m_shapes.size() > 0)
            {
                for (int i = 0; i < m_shapes.size(); i++)
                {
                    BaseShape shape = m_shapes[i];
                    if (shape.m_shapeType == "bar")
                    {
                        for (int j = m_firstVisibleIndex; j <= lastValidIndex; j++)
                        {
                            if (shape.m_showHideDatas.size() > j &&
                              shape.m_showHideDatas[j].ToString() == "0")
                            {
                                continue;
                            }
                            int x = getChartX(j);
                            int y1 = 0;
                            if (shape.m_leftOrRight)
                            {
                                y1 = getChartY(shape.m_divIndex, shape.m_datas[j]);
                            }
                            else
                            {
                                y1 = getChartYInRight(shape.m_divIndex, shape.m_datas[j]);
                            }
                            if (shape.m_style != "2color")
                            {
                                int y2 = 0;
                                if (shape.m_leftOrRight)
                                {
                                    y2 = getChartY(shape.m_divIndex, shape.m_datas2[j]);
                                }
                                else
                                {
                                    y2 = getChartYInRight(shape.m_divIndex, shape.m_datas2[j]);
                                }
                                if (y1 >= y2)
                                {
                                    paint.fillRect(shape.m_color, x - cWidth, y2, x + cWidth, y1);
                                }
                                else
                                {
                                    paint.fillRect(shape.m_color, x - cWidth, y1, x + cWidth, y2);
                                }
                            }
                            else
                            {
                                int y2 = 0;
                                if (shape.m_leftOrRight)
                                {
                                    y2 = getChartY(shape.m_divIndex, 0);
                                }
                                else
                                {
                                    y2 = getChartYInRight(shape.m_divIndex, 0);
                                }
                                if (y1 >= y2)
                                {
                                    paint.drawLine(shape.m_color2, 1, 0, x, y1, x, y2);
                                }
                                else
                                {
                                    paint.drawLine(shape.m_color, 1, 0, x, y1, x, y2);
                                }
                                if (j == lastValidIndex)
                                {
                                    paint.drawLine(shape.m_color2, 1, 0, m_leftVScaleWidth, y2,
                                        size.cx - m_rightVScaleWidth, y2);
                                }
                            }
                        }
                    }
                    else if (shape.m_shapeType == "text")
                    {
                        for (int j = m_firstVisibleIndex; j <= lastValidIndex; j++)
                        {
                            int x = getChartX(j);
                            if (shape.m_datas[j] != 0)
                            {
                                int y1 = 0;
                                if (shape.m_leftOrRight)
                                {
                                    y1 = getChartY(shape.m_divIndex, shape.m_value);
                                }
                                else
                                {
                                    y1 = getChartYInRight(shape.m_divIndex, shape.m_value);
                                }
                                String drawText = shape.m_text;
                                FCSize tSize = paint.textSize(drawText, getFont());
                                paint.drawText(drawText, shape.m_color, getFont(),
                                    new FCRect(x - tSize.cx / 2, y1 - tSize.cy / 2, x + tSize.cx / 2, y1 + tSize.cy / 2));
                            }
                        }
                    }
                    else
                    {
                        if (shape.m_leftOrRight)
                        {
                            drawChartLines(paint, clipRect, shape.m_divIndex,
                                shape.m_datas, shape.m_color,
                                (m_selectShape == shape.m_shapeName) ? true : false);
                        }
                        else
                        {
                            drawChartLinesInRight(paint, clipRect, shape.m_divIndex,
                                shape.m_datas, shape.m_color,
                                (m_selectShape == shape.m_shapeName) ? true : false);
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 绘制十字线
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public virtual void drawChartCrossLine(FCPaint paint, FCRect clipRect)
        {
            if (m_datas == null || m_datas.size() == 0)
            {
                return;
            }
            FCSize size = getSize();
            int candleDivHeight = getCandleDivHeight();
            int volDivHeight = getVolDivHeight();
            int indDivHeight = getIndDivHeight();
            int indDivHeight2 = getIndDivHeight2();
            int crossLineIndex = m_crossStopIndex;
            if (crossLineIndex == -1 || !m_showCrossLine)
            {
                if (m_lastValidIndex != -1)
                {
                    crossLineIndex = m_lastValidIndex;
                }
                else
                {
                    crossLineIndex = m_lastVisibleIndex;
                }
            }
            if (crossLineIndex == -1)
            {
                return;
            }
            if (volDivHeight > 0)
            {
                ArrayList<String> drawTitles = new ArrayList<string>();
                ArrayList<long> drawColors = new ArrayList<long>();
                drawTitles.add("VOL ".ToString() +
                    FCTran.getValueByDigit(m_datas[crossLineIndex].m_volume / m_magnitude, m_volDigit));
                drawColors.add(getTextColor());
                if (m_shapes.size() > 0)
                {
                    for (int i = 0; i < m_shapes.size(); i++)
                    {
                        BaseShape shape = m_shapes[i];
                        if (shape.m_divIndex == 1)
                        {
                            if (shape.m_title.Length > 0)
                            {
                                if (shape.m_shapeType == "bar" && shape.m_style == "2color")
                                {
                                    drawTitles.add(shape.m_title +
                                        " ".ToString() +
                                        FCTran.getValueByDigit(shape.m_datas[crossLineIndex], m_volDigit));
                                    drawColors.add(shape.m_color2);
                                }
                                else
                                {
                                    if (shape.m_shapeType != "text")
                                    {
                                        drawTitles.add(shape.m_title +
                                            " ".ToString() +
                                            FCTran.getValueByDigit(shape.m_datas[crossLineIndex], m_volDigit));
                                        drawColors.add(shape.m_color);
                                        if (shape.m_datas2.size() > 0)
                                        {
                                            drawTitles.add(shape.m_title2 +
                                                " ".ToString() +
                                                FCTran.getValueByDigit(shape.m_datas2[crossLineIndex], m_volDigit));
                                            drawColors.add(shape.m_color2);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                int iLeft = m_leftVScaleWidth + 5;
                for (int i = 0; i < drawTitles.size(); i++)
                {
                    FCSize tSize = paint.textSize(drawTitles[i], getFont());
                    paint.drawText(
                        drawTitles[i], drawColors[i], getFont(), new FCRect(iLeft, candleDivHeight + 5, iLeft + tSize.cx, candleDivHeight + 5 + tSize.cy));
                    iLeft += tSize.cx + 5;
                }
            }
            //上面显示数据  高开低收
            if (m_cycle == "trend")
            {
                ArrayList<String> drawTitles = new ArrayList<string>();
                ArrayList<long> drawColors = new ArrayList<long>();
                if (m_text.Length > 0)
                {
                    drawTitles.add(m_text);
                    drawColors.add(getTextColor());
                }
                if (m_shapes.size() > 0)
                {
                    for (int i = 0; i < m_shapes.size(); i++)
                    {
                        BaseShape shape = m_shapes[i];
                        if (shape.m_divIndex == 0)
                        {
                            if (shape.m_title.Length > 0)
                            {
                                if (shape.m_shapeType == "bar" && shape.m_style == "2color")
                                {
                                    drawTitles.add(shape.m_title +
                                        " ".ToString() +
                                        FCTran.getValueByDigit(shape.m_datas[crossLineIndex], m_candleDigit));
                                    drawColors.add(shape.m_color2);
                                }
                                else
                                {
                                    if (shape.m_shapeType != "text")
                                    {
                                        drawTitles.add(shape.m_title +
                                            " ".ToString() +
                                            FCTran.getValueByDigit(shape.m_datas[crossLineIndex], m_candleDigit));
                                        drawColors.add(shape.m_color);
                                        if (shape.m_datas2.size() > 0)
                                        {
                                            drawTitles.add(shape.m_title2 +
                                                " ".ToString() +
                                                FCTran.getValueByDigit(shape.m_datas2[crossLineIndex], m_candleDigit));
                                            drawColors.add(shape.m_color2);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                int iLeft = m_leftVScaleWidth + 5;
                for (int i = 0; i < drawTitles.size(); i++)
                {
                    FCSize tSize = paint.textSize(drawTitles[i], getFont());
                    paint.drawText(drawTitles[i], drawColors[i], getFont(), new FCRect(iLeft, 5, iLeft + tSize.cx, 5 + tSize.cy));
                    iLeft += tSize.cx + 5;
                }
            }
            else
            {
                ArrayList<String> drawTitles = new ArrayList<string>();
                ArrayList<long> drawColors = new ArrayList<long>();
                if (m_text.Length > 0)
                {
                    drawTitles.add(m_text);
                    drawColors.add(getTextColor());
                }
                if (m_mainIndicator == "MA")
                {
                    if (m_ma5.size() > 0)
                    {
                        drawTitles.add("MA5 ".ToString() +
                            FCTran.getValueByDigit(m_ma5[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("MA5");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_ma10.size() > 0)
                    {
                        drawTitles.add("MA10 ".ToString() +
                            FCTran.getValueByDigit(m_ma10[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("MA10");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_ma20.size() > 0)
                    {
                        drawTitles.add("MA20 ".ToString() +
                            FCTran.getValueByDigit(m_ma20[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("MA20");
                    }
                    drawColors.add(m_indicatorColors[2]);
                    if (m_ma30.size() > 0)
                    {
                        drawTitles.add("MA30 ".ToString() +
                            FCTran.getValueByDigit(m_ma30[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("MA30");
                    }
                    drawColors.add(m_indicatorColors[5]);
                    if (m_ma120.size() > 0)
                    {
                        drawTitles.add("MA120 ".ToString() +
                            FCTran.getValueByDigit(m_ma120[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("MA120");
                    }
                    drawColors.add(m_indicatorColors[4]);
                    if (m_ma250.size() > 0)
                    {
                        drawTitles.add("MA250 ".ToString() +
                            FCTran.getValueByDigit(m_ma250[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("MA250");
                    }
                    drawColors.add(m_indicatorColors[3]);
                }
                else if (m_mainIndicator == "BOLL")
                {
                    if (m_bollMid.size() > 0)
                    {
                        drawTitles.add("MID ".ToString() +
                            FCTran.getValueByDigit(m_bollMid[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("MID");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_bollUp.size() > 0)
                    {
                        drawTitles.add("UP ".ToString() +
                            FCTran.getValueByDigit(m_bollUp[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("UP");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_bollDown.size() > 0)
                    {
                        drawTitles.add("LOW ".ToString() +
                            FCTran.getValueByDigit(m_bollDown[crossLineIndex], m_candleDigit));
                    }
                    else
                    {
                        drawTitles.add("LOW");
                    }
                    drawColors.add(m_indicatorColors[2]);
                }
                if (m_shapes.size() > 0)
                {
                    for (int i = 0; i < m_shapes.size(); i++)
                    {
                        BaseShape shape = m_shapes[i];
                        if (shape.m_divIndex == 0)
                        {
                            if (shape.m_title.Length > 0)
                            {
                                if (shape.m_shapeType == "bar" && shape.m_style == "2color")
                                {
                                    drawTitles.add(shape.m_title +
                                        " ".ToString() +
                                        FCTran.getValueByDigit(shape.m_datas[crossLineIndex], m_candleDigit));
                                    drawColors.add(shape.m_color2);
                                }
                                else
                                {
                                    if (shape.m_shapeType != "text")
                                    {
                                        drawTitles.add(shape.m_title +
                                            " ".ToString() +
                                            FCTran.getValueByDigit(shape.m_datas[crossLineIndex]
                                                , m_candleDigit));
                                        drawColors.add(shape.m_color);
                                        if (shape.m_datas2.size() > 0)
                                        {
                                            drawTitles.add(shape.m_title2 +
                                                " ".ToString() +
                                                FCTran.getValueByDigit(shape.m_datas2[crossLineIndex]
                                                    , m_candleDigit));
                                            drawColors.add(shape.m_color2);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                int iLeft = m_leftVScaleWidth + 5;
                for (int i = 0; i < drawTitles.size(); i++)
                {
                    FCSize tSize = paint.textSize(drawTitles[i], getFont());
                    paint.drawText(drawTitles[i], drawColors[i], getFont(), new FCRect(iLeft, 5, iLeft + tSize.cx, 5 + tSize.cy));
                    iLeft += tSize.cx + 5;
                }
            }
            if (indDivHeight > 0)
            {
                ArrayList<String> drawTitles = new ArrayList<string>();
                ArrayList<long> drawColors = new ArrayList<long>();
                if (m_showIndicator == "MACD")
                {
                    if (m_alldifarr.size() > 0)
                    {
                        drawTitles.add("DIF ".ToString() +
                            FCTran.getValueByDigit(m_alldifarr[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("DIF");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_alldeaarr.size() > 0)
                    {
                        drawTitles.add("DEA ".ToString() +
                            FCTran.getValueByDigit(m_alldeaarr[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("DEA");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_allmacdarr.size() > 0)
                    {
                        drawTitles.add("MACD ".ToString() +
                            FCTran.getValueByDigit(m_allmacdarr[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("MACD");
                    }
                    drawColors.add(m_indicatorColors[4]);
                }
                else if (m_showIndicator == "KDJ")
                {
                    if (m_kdjK.size() > 0)
                    {
                        drawTitles.add("K ".ToString() +
                            FCTran.getValueByDigit(m_kdjK[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("K");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_kdjD.size() > 0)
                    {
                        drawTitles.add("D ".ToString() +
                            FCTran.getValueByDigit(m_kdjD[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("D");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_kdjJ.size() > 0)
                    {
                        drawTitles.add("J ".ToString() +
                            FCTran.getValueByDigit(m_kdjJ[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("J");
                    }
                    drawColors.add(m_indicatorColors[2]);
                }
                else if (m_showIndicator == "RSI")
                {
                    if (m_rsi1.size() > 0)
                    {
                        drawTitles.add("RSI6 ".ToString() +
                            FCTran.getValueByDigit(m_rsi1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("RSI6");
                    }
                    drawColors.add(m_indicatorColors[5]);
                    if (m_rsi2.size() > 0)
                    {
                        drawTitles.add("RSI12 ".ToString() +
                            FCTran.getValueByDigit(m_rsi2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("RSI12");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_rsi3.size() > 0)
                    {
                        drawTitles.add("RSI24 ".ToString() +
                            FCTran.getValueByDigit(m_rsi3[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("RSI24");
                    }
                    drawColors.add(m_indicatorColors[2]);
                }
                else if (m_showIndicator == "BIAS")
                {
                    if (m_bias1.size() > 0)
                    {
                        drawTitles.add("BIAS6 ".ToString() +
                            FCTran.getValueByDigit(m_bias1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BIAS6");
                    }
                    drawColors.add(m_indicatorColors[5]);
                    if (m_bias2.size() > 0)
                    {
                        drawTitles.add("BIAS12 ".ToString() +
                            FCTran.getValueByDigit(m_bias2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BIAS12");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_bias3.size() > 0)
                    {
                        drawTitles.add("BIAS24 ".ToString() +
                            FCTran.getValueByDigit(m_bias3[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BIAS24");
                    }
                    drawColors.add(m_indicatorColors[2]);
                }
                else if (m_showIndicator == "ROC")
                {
                    if (m_roc.size() > 0)
                    {
                        drawTitles.add("ROC ".ToString() +
                            FCTran.getValueByDigit(m_roc[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("ROC");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_rocMa.size() > 0)
                    {
                        drawTitles.add("ROCMA ".ToString() +
                            FCTran.getValueByDigit(m_rocMa[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("ROCMA");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                else if (m_showIndicator == "WR")
                {
                    if (m_wr1.size() > 0)
                    {
                        drawTitles.add("WR5 ".ToString() +
                            FCTran.getValueByDigit(m_wr1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("WR5");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_wr2.size() > 0)
                    {
                        drawTitles.add("WR10 ".ToString() +
                            FCTran.getValueByDigit(m_wr2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("WR10");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                else if (m_showIndicator == "CCI")
                {
                    if (m_cci.size() > 0)
                    {
                        drawTitles.add("CCI ".ToString() +
                            FCTran.getValueByDigit(m_cci[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("CCI");
                    }
                    drawColors.add(m_indicatorColors[0]);
                }
                else if (m_showIndicator == "BBI")
                {
                    if (m_bbi.size() > 0)
                    {
                        drawTitles.add("BBI ".ToString() +
                            FCTran.getValueByDigit(m_bbi[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BBI");
                    }
                    drawColors.add(m_indicatorColors[0]);
                }
                else if (m_showIndicator == "TRIX")
                {
                    if (m_trix.size() > 0)
                    {
                        drawTitles.add("TRIX ".ToString() +
                            FCTran.getValueByDigit(m_trix[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("TRIX");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_trixMa.size() > 0)
                    {
                        drawTitles.add("TRIXMA ".ToString() +
                            FCTran.getValueByDigit(m_trixMa[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("TRIXMA");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                else if (m_showIndicator == "DMA")
                {
                    if (m_dma1.size() > 0)
                    {
                        drawTitles.add("MA10 ".ToString() +
                            FCTran.getValueByDigit(m_dma1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("MA10");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_dma2.size() > 0)
                    {
                        drawTitles.add("MA50 ".ToString() +
                            FCTran.getValueByDigit(m_dma2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("MA50");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                if (m_shapes.size() > 0)
                {
                    for (int i = 0; i < m_shapes.size(); i++)
                    {
                        BaseShape shape = m_shapes[i];
                        if (shape.m_divIndex == 2)
                        {
                            if (shape.m_title.Length > 0)
                            {
                                if (shape.m_shapeType == "bar" && shape.m_style == "2color")
                                {
                                    drawTitles.add(shape.m_title +
                                        " ".ToString() +
                                        FCTran.getValueByDigit(shape.m_datas[crossLineIndex], m_indDigit));
                                    drawColors.add(shape.m_color2);
                                }
                                else
                                {
                                    if (shape.m_shapeType != "text")
                                    {
                                        drawTitles.add(shape.m_title +
                                            " ".ToString() +
                                            FCTran.getValueByDigit(shape.m_datas[crossLineIndex]
                                                , m_indDigit));
                                        drawColors.add(shape.m_color);
                                        if (shape.m_datas2.size() > 0)
                                        {
                                            drawTitles.add(shape.m_title2 +
                                                " ".ToString() +
                                                FCTran.getValueByDigit(shape.m_datas2[crossLineIndex]
                                                    , m_indDigit));
                                            drawColors.add(shape.m_color2);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                int iLeft = m_leftVScaleWidth + 5;
                for (int i = 0; i < drawTitles.size(); i++)
                {
                    FCSize tSize = paint.textSize(drawTitles[i], getFont());
                    paint.drawText(drawTitles[i], drawColors[i], getFont(), new FCRect(iLeft,
                        candleDivHeight + volDivHeight + 5, iLeft + tSize.cx,
                        candleDivHeight + volDivHeight + 5 + tSize.cy));
                    iLeft += tSize.cx + 5;
                }
            }
            if (indDivHeight2 > 0)
            {
                ArrayList<String> drawTitles = new ArrayList<string>();
                ArrayList<long> drawColors = new ArrayList<long>();
                if (m_showIndicator2 == "MACD")
                {
                    if (m_alldifarr.size() > 0)
                    {
                        drawTitles.add("DIF ".ToString() +
                            FCTran.getValueByDigit(m_alldifarr[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("DIF");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_alldeaarr.size() > 0)
                    {
                        drawTitles.add("DEA ".ToString() +
                            FCTran.getValueByDigit(m_alldeaarr[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("DEA");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_allmacdarr.size() > 0)
                    {
                        drawTitles.add("MACD ".ToString() +
                            FCTran.getValueByDigit(m_allmacdarr[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("MACD");
                    }
                    drawColors.add(m_indicatorColors[4]);
                }
                else if (m_showIndicator2 == "KDJ")
                {
                    if (m_kdjK.size() > 0)
                    {
                        drawTitles.add("K ".ToString() +
                            FCTran.getValueByDigit(m_kdjK[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("K");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_kdjD.size() > 0)
                    {
                        drawTitles.add("D ".ToString() +
                            FCTran.getValueByDigit(m_kdjD[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("D");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_kdjJ.size() > 0)
                    {
                        drawTitles.add("J ".ToString() +
                            FCTran.getValueByDigit(m_kdjJ[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("J");
                    }
                    drawColors.add(m_indicatorColors[2]);
                }
                else if (m_showIndicator2 == "RSI")
                {
                    if (m_rsi1.size() > 0)
                    {
                        drawTitles.add("RSI6 ".ToString() +
                            FCTran.getValueByDigit(m_rsi1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("RSI6");
                    }
                    drawColors.add(m_indicatorColors[5]);
                    if (m_rsi2.size() > 0)
                    {
                        drawTitles.add("RSI12 ".ToString() +
                            FCTran.getValueByDigit(m_rsi2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("RSI12");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_rsi3.size() > 0)
                    {
                        drawTitles.add("RSI24 ".ToString() +
                            FCTran.getValueByDigit(m_rsi3[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("RSI24");
                    }
                    drawColors.add(m_indicatorColors[2]);
                }
                else if (m_showIndicator2 == "BIAS")
                {
                    if (m_bias1.size() > 0)
                    {
                        drawTitles.add("BIAS6 ".ToString() +
                            FCTran.getValueByDigit(m_bias1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BIAS6");
                    }
                    drawColors.add(m_indicatorColors[5]);
                    if (m_bias2.size() > 0)
                    {
                        drawTitles.add("BIAS12 ".ToString() +
                            FCTran.getValueByDigit(m_bias2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BIAS12");
                    }
                    drawColors.add(m_indicatorColors[1]);
                    if (m_bias3.size() > 0)
                    {
                        drawTitles.add("BIAS24 ".ToString() +
                            FCTran.getValueByDigit(m_bias3[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BIAS24");
                    }
                    drawColors.add(m_indicatorColors[2]);
                }
                else if (m_showIndicator2 == "ROC")
                {
                    if (m_roc.size() > 0)
                    {
                        drawTitles.add("ROC ".ToString() +
                            FCTran.getValueByDigit(m_roc[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("ROC");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_rocMa.size() > 0)
                    {
                        drawTitles.add("ROCMA ".ToString() +
                            FCTran.getValueByDigit(m_rocMa[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("ROCMA");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                else if (m_showIndicator2 == "WR")
                {
                    if (m_wr1.size() > 0)
                    {
                        drawTitles.add("WR5 ".ToString() +
                            FCTran.getValueByDigit(m_wr1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("WR5");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_wr2.size() > 0)
                    {
                        drawTitles.add("WR10 ".ToString() +
                            FCTran.getValueByDigit(m_wr2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("WR10");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                else if (m_showIndicator2 == "CCI")
                {
                    if (m_cci.size() > 0)
                    {
                        drawTitles.add("CCI ".ToString() +
                            FCTran.getValueByDigit(m_cci[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("CCI");
                    }
                    drawColors.add(m_indicatorColors[0]);
                }
                else if (m_showIndicator2 == "BBI")
                {
                    if (m_bbi.size() > 0)
                    {
                        drawTitles.add("BBI ".ToString() +
                            FCTran.getValueByDigit(m_bbi[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("BBI");
                    }
                    drawColors.add(m_indicatorColors[0]);
                }
                else if (m_showIndicator2 == "TRIX")
                {
                    if (m_trix.size() > 0)
                    {
                        drawTitles.add("TRIX ".ToString() +
                            FCTran.getValueByDigit(m_trix[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("TRIX");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_trixMa.size() > 0)
                    {
                        drawTitles.add("TRIXMA ".ToString() +
                            FCTran.getValueByDigit(m_trixMa[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("TRIXMA");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                else if (m_showIndicator2 == "DMA")
                {
                    if (m_dma1.size() > 0)
                    {
                        drawTitles.add("MA10 ".ToString() +
                            FCTran.getValueByDigit(m_dma1[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("MA10");
                    }
                    drawColors.add(m_indicatorColors[0]);
                    if (m_dma2.size() > 0)
                    {
                        drawTitles.add("MA50 ".ToString() +
                            FCTran.getValueByDigit(m_dma2[crossLineIndex], m_indDigit));
                    }
                    else
                    {
                        drawTitles.add("MA50");
                    }
                    drawColors.add(m_indicatorColors[1]);
                }
                if (m_shapes.size() > 0)
                {
                    for (int i = 0; i < m_shapes.size(); i++)
                    {
                        BaseShape shape = m_shapes[i];
                        if (shape.m_divIndex == 3)
                        {
                            if (shape.m_title.Length > 0)
                            {
                                if (shape.m_shapeType == "bar" && shape.m_style == "2color")
                                {
                                    drawTitles.add(shape.m_title +
                                        " ".ToString() +
                                        FCTran.getValueByDigit(shape.m_datas[crossLineIndex], m_indDigit2));
                                    drawColors.add(shape.m_color2);
                                }
                                else
                                {
                                    if (shape.m_shapeType != "text")
                                    {
                                        drawTitles.add(shape.m_title +
                                            " ".ToString() +
                                            FCTran.getValueByDigit(shape.m_datas[crossLineIndex]
                                                , m_indDigit2));
                                        drawColors.add(shape.m_color);
                                        if (shape.m_datas2.size() > 0)
                                        {
                                            drawTitles.add(shape.m_title2 +
                                                " ".ToString() +
                                                FCTran.getValueByDigit(shape.m_datas2[crossLineIndex]
                                                    , m_indDigit2));
                                            drawColors.add(shape.m_color2);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                if (drawTitles.size() > 0)
                {
                    int iLeft = m_leftVScaleWidth + 5;
                    for (int i = 0; i < drawTitles.size(); i++)
                    {
                        FCSize tSize = paint.textSize(drawTitles[i], getFont());
                        paint.drawText(drawTitles[i], drawColors[i], getFont(), new FCRect(iLeft,
                            candleDivHeight + volDivHeight + indDivHeight + 5 + tSize.cy / 2, iLeft + tSize.cx,
                            candleDivHeight + volDivHeight + indDivHeight + 5 + tSize.cy / 2 + tSize.cy));
                        iLeft += tSize.cx + 5;
                    }
                }
            }

            if (this == m_native.m_touchMoveView || this == m_native.m_touchDownView)
            {
                String rightText = "";
                if (m_touchPosition.y < candleDivHeight)
                {
                    rightText = FCTran.getValueByDigit(getChartValue(m_touchPosition)
                        , m_candleDigit);
                }
                else if (m_touchPosition.y > candleDivHeight &&
                    m_touchPosition.y < candleDivHeight + volDivHeight)
                {
                    rightText = FCTran.getValueByDigit(getChartValue(m_touchPosition) / m_magnitude
                        , m_volDigit);
                }
                else if (m_touchPosition.y > candleDivHeight + volDivHeight &&
                  m_touchPosition.y < candleDivHeight + volDivHeight + indDivHeight)
                {
                    rightText = FCTran.getValueByDigit(getChartValue(m_touchPosition)
                        , m_indDigit);
                }
                else if (m_touchPosition.y >
                      candleDivHeight + volDivHeight + indDivHeight &&
                  m_touchPosition.y <
                      candleDivHeight + volDivHeight + indDivHeight + indDivHeight2)
                {
                    rightText = FCTran.getValueByDigit(getChartValue(m_touchPosition)
                        , m_indDigit2);
                }

                int drawY = m_touchPosition.y;
                if (drawY > size.cy - m_hScaleHeight)
                {
                    drawY = size.cy - m_hScaleHeight;
                }
                FCSize tSize = paint.textSize(rightText, getFont());
                if (m_leftVScaleWidth > 0)
                {
                    paint.fillRect(m_crossTipColor, m_leftVScaleWidth - tSize.cx, drawY - tSize.cy / 2 - 4,
                        m_leftVScaleWidth, drawY + tSize.cy / 2 + 3);
                    paint.drawText(rightText, getTextColor(), getFont(),
                        new FCRect(m_leftVScaleWidth - tSize.cx, drawY - tSize.cy / 2, m_leftVScaleWidth, drawY + tSize.cy / 2));
                }
                if (m_rightVScaleWidth > 0)
                {
                    paint.fillRect(m_crossTipColor, size.cx - m_rightVScaleWidth, drawY - tSize.cy / 2 - 4,
                        size.cx - m_rightVScaleWidth + tSize.cx, drawY + tSize.cy / 2 + 3);
                    paint.drawText(rightText, getTextColor(), getFont(),
                        new FCRect(size.cx - m_rightVScaleWidth, drawY - tSize.cy / 2, size.cx - m_rightVScaleWidth + tSize.cx, drawY + tSize.cy / 2));
                }
                //绘制十字线
                int drawX = getChartX(m_crossStopIndex);
                if (m_targetOldX == 0 && m_targetOldX2 == 0)
                {
                    drawX = m_touchPosition.x;
                }
                if (drawX < m_leftVScaleWidth)
                {
                    drawX = m_leftVScaleWidth;
                }
                if (drawX > size.cx - m_rightVScaleWidth)
                {
                    drawX = size.cx - m_rightVScaleWidth;
                }
                if (m_showCrossLine)
                {
                    paint.drawLine(m_crossLineColor, m_lineWidthChart, 0,
                        m_leftVScaleWidth, drawY, size.cx - m_rightVScaleWidth, drawY);
                    paint.drawLine(m_crossLineColor, m_lineWidthChart, 0, drawX, 0,
                        drawX, size.cy - m_hScaleHeight);
                }
                if (m_crossStopIndex != -1)
                {
                    double dateNum = m_datas[m_crossStopIndex].m_date;
                    String xText = dateNum.ToString();
                    DateTime dt = FCTran.numToDate(dateNum);
                    if (m_hScaleFormat.Length > 0)
                    {
                        xText = dt.ToString(m_hScaleFormat);
                    }
                    else
                    {
                        if (m_cycle == "day")
                        {
                            xText = dt.ToString("yyyy-MM-dd");
                        }
                        else if (m_cycle == "minute")
                        {
                            xText = dt.ToString("yyyy-MM-dd hh:mm");
                        }
                        else if (m_cycle == "trend")
                        {
                            xText = dt.ToString("HH:mm");
                        }
                        else if (m_cycle == "second")
                        {
                            xText = dt.ToString("HH:mm:ss");
                        }
                        else if (m_cycle == "tick")
                        {
                            xText = (m_crossStopIndex + 1).ToString();
                        }
                    }
                    FCSize xSize = paint.textSize(xText, getFont());
                    paint.fillRect(
                        m_crossTipColor,
                        drawX - xSize.cx / 2 - 2,
                        candleDivHeight + volDivHeight + indDivHeight,
                        drawX + xSize.cx / 2 + 2,
                        candleDivHeight + volDivHeight + indDivHeight + xSize.cy + 6);
                    paint.drawText(xText, getTextColor(), getFont(), new FCRect(drawX - xSize.cx / 2,
                        candleDivHeight + volDivHeight + indDivHeight + 3, drawX + xSize.cx / 2,
                        candleDivHeight + volDivHeight + indDivHeight + 3 + xSize.cy));
                }
            }
        }

        /// <summary>
        /// 绘制刻度
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public virtual void drawChartScale(FCPaint paint, FCRect clipRect)
        {
            FCSize size = getSize();
            if (m_leftVScaleWidth > 0)
            {
                paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                    m_leftVScaleWidth, 0, m_leftVScaleWidth,
                    size.cy - m_hScaleHeight);
            }
            if (m_rightVScaleWidth > 0)
            {
                paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                    size.cx - m_rightVScaleWidth, 0, size.cx - m_rightVScaleWidth,
                    size.cy - m_hScaleHeight);
            }
            if (m_hScaleHeight > 0)
            {
                paint.drawLine(m_scaleColor, m_lineWidthChart, 0, 0,
                    size.cy - m_hScaleHeight, size.cx, size.cy - m_hScaleHeight);
            }
            int candleDivHeight = getCandleDivHeight();
            int volDivHeight = getVolDivHeight();
            int indDivHeight = getIndDivHeight();
            int indDivHeight2 = getIndDivHeight2();
            if (volDivHeight > 0)
            {
                paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                    m_leftVScaleWidth, candleDivHeight, size.cx - m_rightVScaleWidth, candleDivHeight);
            }
            if (indDivHeight > 0)
            {
                paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                    m_leftVScaleWidth, candleDivHeight + volDivHeight,
                    size.cx - m_rightVScaleWidth,
                    candleDivHeight + volDivHeight);
            }
            if (indDivHeight2 > 0)
            {
                paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                    m_leftVScaleWidth, candleDivHeight + volDivHeight + indDivHeight,
                    size.cx - m_rightVScaleWidth,
                    candleDivHeight + volDivHeight + indDivHeight);
            }
            if (m_datas.size() > 0)
            {
                FCPoint topPoint = new FCPoint(0, 20);
                FCPoint bottomPoint = new FCPoint(0, candleDivHeight - 10);
                double candleMax = getChartValue(topPoint);
                double candleMin = getChartValue(bottomPoint);
                chartGridScale(candleMin, candleMax, (candleDivHeight - m_candlePaddingTop - m_candlePaddingBottom) / 2,
                    m_vScaleDistance, m_vScaleDistance / 2,
                    (candleDivHeight - m_candlePaddingTop - m_candlePaddingBottom) / m_vScaleDistance);
                if (m_gridStep > 0)
                {
                    ArrayList<double> drawValues = new ArrayList<double>();
                    bool isTrend = m_cycle == "trend";
                    double firstOpen = m_firstOpen;
                    if (isTrend)
                    {
                        if (firstOpen == 0)
                        {
                            firstOpen = m_datas[m_firstVisibleIndex].m_close;
                        }
                        double subValue = (candleMax - candleMin);
                        int count = (candleDivHeight -
                                m_candlePaddingTop -
                                m_candlePaddingBottom) /
                            m_vScaleDistance;
                        if (count > 0)
                        {
                            subValue /= count;
                        }
                        double start = firstOpen;
                        while (start < candleMax)
                        {
                            start += subValue;
                            if (start <= candleMax)
                            {
                                drawValues.add(start);
                            }
                        }
                        start = firstOpen;
                        while (start > candleMin)
                        {
                            start -= subValue;
                            if (start >= candleMin)
                            {
                                drawValues.add(start);
                            }
                        }
                    }
                    else
                    {
                        double start = 0;
                        if (candleMin >= 0)
                        {
                            while (start + m_gridStep < candleMin)
                            {
                                start += m_gridStep;
                            }
                        }
                        else
                        {
                            while (start - m_gridStep > candleMin)
                            {
                                start -= m_gridStep;
                            }
                        }

                        while (start <= candleMax)
                        {
                            if (start > candleMin)
                            {
                                drawValues.add(start);
                            }
                            start += m_gridStep;
                        }
                    }
                    drawValues.add(firstOpen);
                    for (int i = 0; i < drawValues.size(); i++)
                    {
                        double start = drawValues[i];
                        int hAxisY = getChartY(0, start);
                        if (hAxisY < 1 || hAxisY > candleDivHeight)
                        {
                            continue;
                        }
                        paint.drawLine(m_gridColor, m_lineWidthChart, 0,
                            m_leftVScaleWidth, hAxisY,
                            size.cx - m_rightVScaleWidth, hAxisY);
                        paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                            m_leftVScaleWidth - 8, hAxisY, m_leftVScaleWidth, hAxisY);
                        paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                            size.cx - m_rightVScaleWidth, hAxisY,
                           size.cx - m_rightVScaleWidth + 8, hAxisY);

                        String drawText = FCTran.getValueByDigit(start, m_candleDigit);

                        FCSize tSize = paint.textSize(drawText, getFont());
                        if (isTrend)
                        {
                            double diffRange = ((start - firstOpen) / firstOpen * 100);
                            String diffRangeStr = FCTran.getValueByDigit(diffRange, 2) + "%".ToString();
                            FCSize dSize = paint.textSize(diffRangeStr, getFont());
                            if (diffRange >= 0)
                            {
                                paint.drawText(diffRangeStr, m_upColor, getFont(),
                                    new FCRect(size.cx - m_rightVScaleWidth + 10,
                                    hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + dSize.cx,
                                    hAxisY + tSize.cy / 2));
                            }
                            else
                            {
                                paint.drawText(diffRangeStr, m_downColor, getFont(),
                                    new FCRect(size.cx - m_rightVScaleWidth + 10,
                                    hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + dSize.cx,
                                    hAxisY + tSize.cy / 2));
                            }
                        }
                        else
                        {
                            if (m_vScaleTextColor != FCColor.None)
                            {
                                paint.drawText(drawText, m_vScaleTextColor, getFont(), new FCRect(size.cx - m_rightVScaleWidth + 10,
                                    hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx,
                                    hAxisY + tSize.cy / 2));
                            }
                            else
                            {
                                paint.drawText(drawText, getTextColor(), getFont(), new FCRect(size.cx - m_rightVScaleWidth + 10,
                                    hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx,
                                    hAxisY + tSize.cy / 2));
                            }
                        }
                        if (m_vScaleTextColor != FCColor.None)
                        {
                            paint.drawText(drawText, m_vScaleTextColor, getFont(),
                                new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                        }
                        else
                        {
                            paint.drawText(drawText, getTextColor(), getFont(),
                                new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                        }
                    }
                }
                topPoint = new FCPoint(0, candleDivHeight + 10);
                bottomPoint = new FCPoint(0, candleDivHeight + volDivHeight - 10);
                double volMax = getChartValue(topPoint);
                double volMin = getChartValue(bottomPoint);
                chartGridScale(volMin, volMax, (volDivHeight - m_volPaddingTop - m_volPaddingBottom) / 2,
                    m_vScaleDistance, m_vScaleDistance / 2,
                    (volDivHeight - m_volPaddingTop - m_volPaddingBottom) / m_vScaleDistance);
                if (m_gridStep > 0)
                {
                    double start = 0;
                    if (volMin >= 0)
                    {
                        while (start + m_gridStep < volMin)
                        {
                            start += m_gridStep;
                        }
                    }
                    else
                    {
                        while (start - m_gridStep > volMin)
                        {
                            start -= m_gridStep;
                        }
                    }
                    while (start <= volMax)
                    {
                        if (start > volMin)
                        {
                            int hAxisY = getChartY(1, start);
                            if (hAxisY < candleDivHeight ||
                                hAxisY > candleDivHeight + volDivHeight)
                            {
                                start += m_gridStep;
                                continue;
                            }
                            paint.drawLine(m_gridColor, m_lineWidthChart, 0, m_leftVScaleWidth,
                                hAxisY, size.cx - m_rightVScaleWidth, hAxisY);
                            paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                                m_leftVScaleWidth - 8, hAxisY, m_leftVScaleWidth, hAxisY);
                            paint.drawLine(m_scaleColor, m_lineWidthChart, 0, size.cx - m_rightVScaleWidth,
                                hAxisY, size.cx - m_rightVScaleWidth + 8, hAxisY);
                            String drawText =
                                FCTran.getValueByDigit(start / m_magnitude, m_volDigit);
                            FCSize tSize = paint.textSize(drawText, getFont());
                            if (m_vScaleTextColor != FCColor.None)
                            {
                                paint.drawText(drawText, m_vScaleTextColor, getFont(),
                                    new FCRect(size.cx - m_rightVScaleWidth + 10,
                                    hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx,
                                    hAxisY + tSize.cy / 2));
                                paint.drawText(drawText, m_vScaleTextColor, getFont(),
                                    new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                            }
                            else
                            {
                                paint.drawText(drawText, getTextColor(), getFont(),
                                    new FCRect(size.cx - m_rightVScaleWidth + 10,
                                    hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx,
                                    hAxisY + tSize.cy / 2));
                                paint.drawText(drawText, getTextColor(), getFont(),
                                    new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                            }
                        }
                        start += m_gridStep;
                    }
                }
                if (indDivHeight > 0)
                {
                    topPoint = new FCPoint(0, candleDivHeight + volDivHeight + 10);
                    bottomPoint =
                        new FCPoint(0, candleDivHeight + volDivHeight + indDivHeight - 10);
                    double indMax = getChartValue(topPoint);
                    double indMin = getChartValue(bottomPoint);
                    chartGridScale(indMin, indMax, (indDivHeight - m_indPaddingTop - m_indPaddingBottom) / 2,
                        m_vScaleDistance, m_vScaleDistance / 2,
                        (indDivHeight - m_indPaddingTop - m_indPaddingBottom) / m_vScaleDistance);
                    if (m_gridStep > 0)
                    {
                        double start = 0;
                        if (indMin >= 0)
                        {
                            while (start + m_gridStep < indMin)
                            {
                                start += m_gridStep;
                            }
                        }
                        else
                        {
                            while (start - m_gridStep > indMin)
                            {
                                start -= m_gridStep;
                            }
                        }

                        while (start <= indMax)
                        {
                            if (start > indMin)
                            {
                                int hAxisY = getChartY(2, start);
                                if (hAxisY < candleDivHeight + volDivHeight ||
                                    hAxisY > candleDivHeight + volDivHeight + indDivHeight)
                                {
                                    start += m_gridStep;
                                    continue;
                                }
                                paint.drawLine(m_gridColor, m_lineWidthChart, 0, m_leftVScaleWidth, hAxisY, size.cx - m_rightVScaleWidth, hAxisY);
                                paint.drawLine(m_scaleColor, m_lineWidthChart, 0, m_leftVScaleWidth - 8, hAxisY, m_leftVScaleWidth, hAxisY);
                                paint.drawLine(m_scaleColor, m_lineWidthChart, 0,
                                    size.cx - m_rightVScaleWidth, hAxisY, size.cx - m_rightVScaleWidth + 8, hAxisY);
                                String drawText = FCTran.getValueByDigit(start, m_indDigit);
                                FCSize tSize = paint.textSize(drawText, getFont());
                                if (m_vScaleTextColor != FCColor.None)
                                {
                                    paint.drawText(drawText, m_vScaleTextColor, getFont(),
                                        new FCRect(size.cx - m_rightVScaleWidth + 10,
                                        hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx,
                                        hAxisY + tSize.cy / 2));
                                    paint.drawText(drawText, m_vScaleTextColor, getFont(),
                                        new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                                }
                                else
                                {
                                    paint.drawText(drawText, getTextColor(), getFont(),
                                        new FCRect(size.cx - m_rightVScaleWidth + 10,
                                        hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx,
                                        hAxisY + tSize.cy / 2));
                                    paint.drawText(drawText, getTextColor(), getFont(),
                                        new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                                }
                            }
                            start += m_gridStep;
                        }
                    }
                }
                if (indDivHeight2 > 0)
                {
                    topPoint = new FCPoint(0, candleDivHeight + volDivHeight + indDivHeight + 10);
                    bottomPoint = new FCPoint(0,
                        candleDivHeight + volDivHeight + indDivHeight + indDivHeight2 - 10);
                    double indMax2 = getChartValue(topPoint);
                    double indMin2 = getChartValue(bottomPoint);
                    chartGridScale(indMin2, indMax2, (indDivHeight2 - m_indPaddingTop2 - m_indPaddingBottom2) / 2, m_vScaleDistance, m_vScaleDistance / 2, (indDivHeight2 - m_indPaddingTop2 - m_indPaddingBottom2) /
                            m_vScaleDistance);
                    if (m_gridStep > 0)
                    {
                        double start = 0;
                        if (indMin2 >= 0)
                        {
                            while (start + m_gridStep < indMin2)
                            {
                                start += m_gridStep;
                            }
                        }
                        else
                        {
                            while (start - m_gridStep > indMin2)
                            {
                                start -= m_gridStep;
                            }
                        }

                        while (start <= indMax2)
                        {
                            if (start > indMin2)
                            {
                                int hAxisY = getChartY(3, start);
                                if (hAxisY < candleDivHeight + volDivHeight + indDivHeight || hAxisY > candleDivHeight + volDivHeight + indDivHeight + indDivHeight2)
                                {
                                    start += m_gridStep;
                                    continue;
                                }
                                paint.drawLine(m_gridColor, m_lineWidthChart, 0, m_leftVScaleWidth, hAxisY, size.cx - m_rightVScaleWidth, hAxisY);
                                paint.drawLine(m_scaleColor, m_lineWidthChart, 0, m_leftVScaleWidth - 8, hAxisY, m_leftVScaleWidth, hAxisY);
                                paint.drawLine(m_scaleColor, m_lineWidthChart, 0, size.cx - m_rightVScaleWidth, hAxisY, size.cx - m_rightVScaleWidth + 8, hAxisY);
                                String drawText = FCTran.getValueByDigit(start, m_indDigit);
                                FCSize tSize = paint.textSize(drawText, getFont());
                                if (m_vScaleTextColor != FCColor.None)
                                {
                                    paint.drawText(drawText, m_vScaleTextColor, getFont(), new FCRect(size.cx - m_rightVScaleWidth + 10, hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx, hAxisY + tSize.cy / 2));
                                    paint.drawText(drawText, m_vScaleTextColor, getFont(),
                                        new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                                }
                                else
                                {
                                    paint.drawText(drawText, getTextColor(), getFont(), new FCRect(size.cx - m_rightVScaleWidth + 10, hAxisY - tSize.cy / 2, size.cx - m_rightVScaleWidth + 10 + tSize.cx, hAxisY + tSize.cy / 2));
                                    paint.drawText(drawText, getTextColor(), getFont(),
                                        new FCRect(m_leftVScaleWidth - tSize.cx - 10, hAxisY - tSize.cy / 2, m_leftVScaleWidth - 10, hAxisY + tSize.cy / 2));
                                }
                            }
                            start += m_gridStep;
                        }
                    }
                }
            }
            if (m_datas.size() > 0 && m_hScaleHeight > 0)
            {
                double dLeft = m_leftVScaleWidth + 10;
                for (int i = m_firstVisibleIndex; i <= m_lastVisibleIndex; i++)
                {
                    double dateNum = m_datas[i].m_date;
                    String xText = dateNum.ToString();
                    DateTime dt = FCTran.numToDate(dateNum);
                    if (m_hScaleFormat.Length > 0)
                    {
                        xText = dt.ToString(m_hScaleFormat);
                    }
                    else
                    {
                        if (m_cycle == "day")
                        {
                            xText = dt.ToString("yyyy-MM-dd");
                        }
                        else if (m_cycle == "minute")
                        {
                            xText = dt.ToString("yyyy-MM-dd HH:mm");
                        }
                        else if (m_cycle == "trend")
                        {
                            xText = dt.ToString("HH:mm");
                        }
                        else if (m_cycle == "second")
                        {
                            xText = dt.ToString("HH:mm:ss");
                        }
                        else if (m_cycle == "tick")
                        {
                            xText = (m_crossStopIndex + 1).ToString();
                        }
                    }
                    FCSize tSize = paint.textSize(xText, getFont());
                    int x = getChartX(i);
                    int dx = x - tSize.cx / 2;
                    if (dx > dLeft && dx < size.cx - m_rightVScaleWidth - 10)
                    {
                        paint.drawLine(m_scaleColor, m_lineWidthChart, 0, x, size.cy - m_hScaleHeight, x, size.cy - m_hScaleHeight + 8);
                        if (m_hScaleTextColor != FCColor.None)
                        {
                            paint.drawText(xText, m_hScaleTextColor, getFont(), new FCRect(dx, size.cy - m_hScaleHeight + 8 - tSize.cy / 2 + 7, dx + tSize.cx, size.cy - m_hScaleHeight + 8 + tSize.cy / 2 + 7));
                        }
                        else
                        {
                            paint.drawText(xText, getTextColor(), getFont(), new FCRect(dx, size.cy - m_hScaleHeight + 8 - tSize.cy / 2 + 7, dx + tSize.cx, size.cy - m_hScaleHeight + 8 + tSize.cy / 2 + 7));
                        }
                        i = i + (int)((tSize.cx + m_hScaleTextDistance) / m_hScalePixel) + 1;
                    }
                }
            }
        }

        /// <summary>
        /// 根据三点计算圆心
        /// </summary>
        /// <param name="x1">横坐标1</param>
        /// <param name="y1">纵坐标1</param>
        /// <param name="x2">横坐标2</param>
        /// <param name="y2">纵坐标2</param>
        /// <param name="x3">横坐标3</param>
        /// <param name="y3">纵坐标3</param>
        public virtual void ellipseOR(double x1, double y1, double x2, double y2, double x3, double y3)
        {
            m_oXChart = ((y3 - y1) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1) +
                    (y2 - y1) * (y1 * y1 - y3 * y3 + x1 * x1 - x3 * x3)) /
                (2 * (x2 - x1) * (y3 - y1) - 2 * (x3 - x1) * (y2 - y1));
            m_oYChart = ((x3 - x1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) +
                    (x2 - x1) * (x1 * x1 - x3 * x3 + y1 * y1 - y3 * y3)) /
                (2 * (y2 - y1) * (x3 - x1) - 2 * (y3 - y1) * (x2 - x1));
            m_rChart = Math.Sqrt((x1 - m_oXChart) * (x1 - m_oXChart) + (y1 - m_oYChart) * (y1 - m_oYChart));
        }

        /// <summary>
        /// 判断点是否在椭圆上
        /// </summary>
        /// <param name="x">横坐标</param>
        /// <param name="y">纵坐标</param>
        /// <param name="oX">坐标起始X</param>
        /// <param name="oY">坐标起始Y</param>
        /// <param name="a">椭圆参数a</param>
        /// <param name="b">椭圆参数b</param>
        /// <returns></returns>
        public virtual bool ellipseHasPoint(double x, double y, double oX, double oY, double a, double b)
        {
            x -= oX;
            y -= oY;
            if (a == 0 && b == 0 && x == 0 && y == 0)
            {
                return true;
            }
            if (a == 0)
            {
                if (x == 0 && y >= -b && y <= b)
                {
                    return false;
                }
            }
            if (b == 0)
            {
                if (y == 0 && x >= -a && x <= a)
                {
                    return true;
                }
            }
            if ((x * x) / (a * a) + (y * y) / (b * b) >= 0.8 &&
                (x * x) / (a * a) + (y * y) / (b * b) <= 1.2)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 计算斐波那契数列
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns></returns>
        public virtual int fibonacciValue(int index)
        {
            if (index < 1)
            {
                return 0;
            }
            else
            {
                ArrayList<int> vList = new ArrayList<int>();
                for (int i = 0; i < index; i++)
                {
                    vList.add(0);
                }
                int result = 0;
                for (int i = 0; i <= index - 1; i++)
                {
                    if (i == 0 || i == 1)
                    {
                        vList[i] = 1;
                    }
                    else
                    {
                        vList[i] = vList[i - 1] + vList[i - 2];
                    }
                }
                result = vList[index - 1];
                return result;
            }
        }

        /// <summary>
        /// 获取视图类型
        /// </summary>
        /// <returns></returns>
        public override string getViewType()
        {
            return "Chart";
        }

        /// <summary>
        /// 获取图表的区域
        /// </summary>
        /// <param name="plot">画线</param>
        public virtual void getCandleRange(FCPlot plot)
        {
            int bIndex = getChartIndexByDate(plot.m_key1);
            int eIndex = getChartIndexByDate(plot.m_key2);
            int tempBIndex = Math.Min(bIndex, eIndex);
            int tempEIndex = Math.Max(bIndex, eIndex);
            bIndex = tempBIndex;
            eIndex = tempEIndex;
            ArrayList<double> highList = new ArrayList<double>();
            ArrayList<double> lowList = new ArrayList<double>();
            for (int i = bIndex; i <= eIndex; i++)
            {
                highList.add(m_datas[i].m_high);
                lowList.add(m_datas[i].m_low);
            }
            m_nHighChart = maxValue(highList);
            m_nLowChart = minValue(lowList);
        }

        /// <summary>
        /// 计算EMA
        /// </summary>
        /// <param name="n">周期</param>
        /// <param name="value">当前数据</param>
        /// <param name="lastEMA">上期数据</param>
        /// <returns></returns>
        public virtual double getEMA(int n, double value, double lastEMA)
        {
            return (value * 2 + lastEMA * (n - 1)) / (n + 1);
        }

        /// <summary>
        /// 计算MACD
        /// </summary>
        /// <param name="dif">DIF数据</param>
        /// <param name="dea">DEA数据</param>
        /// <returns></returns>
        public virtual ArrayList<double> getMACD(ArrayList<double> dif, ArrayList<double> dea)
        {
            ArrayList<double> result = new ArrayList<double>();
            for (int i = 0; i < dif.size(); i++)
            {
                result.add((dif[i] - dea[i]) * 2);
            }
            return result;
        }

        /// <summary>
        /// 计算DIF
        /// </summary>
        /// <param name="close12">12日数据</param>
        /// <param name="close26">26日数据</param>
        /// <returns></returns>
        public virtual ArrayList<double> getDIF(ArrayList<double> close12, ArrayList<double> close26)
        {
            ArrayList<double> result = new ArrayList<double>();
            for (int i = 0; i < close12.size(); i++)
            {
                result.add(close12[i] - close26[i]);
            }
            return result;
        }

        /// <summary>
        /// 根据日期获取索引
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public virtual int getChartIndexByDate(double date)
        {
            int index = -1;
            for (int i = 0; i < m_datas.size(); i++)
            {
                if (m_datas[i].m_date == date)
                {
                    index = i;
                    break;
                }
            }
            return index;
        }

        /// <summary>
        /// 获取百分比线的刻度
        /// </summary>
        /// <param name="y1">纵坐标1</param>
        /// <param name="y2">纵坐标2</param>
        /// <returns></returns>
        public virtual ArrayList<int> getPercentParams(double y1, double y2)
        {
            double y0 = 0, y25 = 0, y50 = 0, y75 = 0, y100 = 0;
            y0 = y1;
            y25 = y1 <= y2 ? y1 + (y2 - y1) / 4 : y2 + (y1 - y2) * 3 / 4;
            y50 = y1 <= y2 ? y1 + (y2 - y1) / 2 : y2 + (y1 - y2) / 2;
            y75 = y1 <= y2 ? y1 + (y2 - y1) * 3 / 4 : y2 + (y1 - y2) / 4;
            y100 = y2;
            ArrayList<int> list = new ArrayList<int>();
            list.add((int)y0);
            list.add((int)y25);
            list.add((int)y50);
            list.add((int)y75);
            list.add((int)y100);
            return list;
        }

        /// <summary>
        /// 获取TRIX的数据
        /// </summary>
        public virtual void getTRIXData(ArrayList<double> ticks, int m, ArrayList<double> trixArr, ArrayList<double> matrixArr)
        {
            int length = ticks.size();
            ArrayList<double> mtrArr = new ArrayList<double>();
            ArrayList<double> emaArr1 = new ArrayList<double>();
            emaArr1.add(ticks[0]);
            for (int i = 1; i < length; i++)
            {
                emaArr1.add(getEMA(m, ticks[i], emaArr1[i - 1]));
            }

            ArrayList<double> emaArr2 = new ArrayList<double>();
            emaArr2.add(emaArr1[0]);
            for (int i = 1; i < length; i++)
            {
                emaArr2.add(getEMA(m, emaArr1[i], emaArr2[i - 1]));
            }

            mtrArr.add(emaArr2[0]);
            for (int i = 1; i < length; i++)
            {
                mtrArr.add(getEMA(m, emaArr2[i], mtrArr[i - 1]));
            }

            ArrayList<double> refV = refValue(mtrArr, 1);
            for (int i = 0; i < length; i++)
            {
                double trix = 100 * (mtrArr[i] - refV[i]) / refV[i];
                trixArr.add(trix);
            }

            ArrayList<double> matrixArrCopy = maValue(trixArr, m);
            for (int i = 0; i < matrixArrCopy.size(); i++)
            {
                matrixArr.add(matrixArrCopy[i]);
            }
        }

        /// <summary>
        /// 计算boll指标,ma的周期为20日
        /// </summary>
        public virtual void getBollData(ArrayList<double> ticks, int maDays, ArrayList<double> ups, ArrayList<double> mas, ArrayList<double> lows)
        {
            int tickBegin = maDays - 1;
            double maSum = 0;
            double p = 0;
            for (int i = 0; i < ticks.size(); i++)
            {
                double c = ticks[i];
                double ma = 0;
                double md = 0;
                int bstart = 0;
                double mdSum = 0;
                maSum = maSum + c;
                if (i >= tickBegin)
                {
                    maSum = maSum - p;
                    ma = maSum / maDays;
                    bstart = i - tickBegin;
                    p = ticks[bstart];
                    mas.add(ma);
                    bstart = i - tickBegin;
                    p = ticks[bstart];
                    ArrayList<double> values = new ArrayList<double>();
                    for (int j = bstart; j < bstart + maDays; j++)
                    {
                        values.add(ticks[j]);
                    }
                    mdSum = standardDeviationSum(values, ma);
                    md = Math.Sqrt(mdSum / maDays);
                    ups.add(ma + 2 * md);
                    lows.add(ma - 2 * md);
                }
                else
                {
                    ma = maSum / (i + 1);
                    mas.add(ma);
                    ArrayList<double> values = new ArrayList<double>();
                    for (int j = 0; j < i + 1; j++)
                    {
                        values.add(ticks[j]);
                    }
                    mdSum = standardDeviationSum(values, ma);
                    md = Math.Sqrt(mdSum / (i + 1));
                    ups.add(ma + 2 * md);
                    lows.add(ma - 2 * md);
                }
            }
        }

        /// <summary>
        /// 计算kdj指标
        /// </summary>
        public virtual void getKDJData(ArrayList<double> highArr, ArrayList<double> lowArr, ArrayList<double> closeArr, int n, int m1, int m2, ArrayList<double> ks, ArrayList<double> ds, ArrayList<double> js)
        {
            ArrayList<double> rsvs = new ArrayList<double>();
            double lastK = 0;
            double lastD = 0;
            double curK = 0;
            double curD = 0;
            for (int i = 0; i < closeArr.size(); i++)
            {
                ArrayList<double> highList = new ArrayList<double>();
                ArrayList<double> lowList = new ArrayList<double>();
                int startIndex = i - n;
                if (startIndex < 0)
                {
                    startIndex = 0;
                }

                for (int j = startIndex; j <= i; j++)
                {
                    highList.add(highArr[j]);
                    lowList.add(lowArr[j]);
                }

                double close = closeArr[i];
                double maxHigh = 0, minLow = 0;
                for (int m = 0; m < highList.size(); m++)
                {
                    double high = highList[m];
                    double low = lowList[m];
                    if (high > maxHigh)
                    {
                        maxHigh = high;
                    }
                    if (low < minLow)
                    {
                        minLow = low;
                    }
                }
                if (maxHigh == minLow)
                {
                    rsvs.add(0);
                }
                else
                {
                    rsvs.add(100 * (close - minLow) / (maxHigh - minLow));
                }
                if (i == 0)
                {
                    lastK = rsvs[i];
                    lastD = rsvs[i];
                }
                curK = lastK * (m1 - 1) / m1 + 1.0 / m1 * rsvs[i];
                ks.add(curK);
                lastK = curK;

                curD = lastD * (m2 - 1) / m2 + 1.0 / m2 * curK;
                ds.add(curD);
                lastD = curD;

                js.add(3.0 * curK - 2.0 * curD);
            }
        }

        /// <summary>
        /// 计算rsi指标,分别返回以6日，12日，24日为参考基期的RSI值
        /// </summary>
        public virtual void getRSIData(ArrayList<double> ticks, int n1, int n2, int n3, ArrayList<double> rsi1, ArrayList<double> rsi2, ArrayList<double> rsi3)
        {
            double lastClosePx = ticks[0];
            double lastSm1 = 0;
            double lastSa1 = 0;
            double lastSm2 = 0;
            double lastSa2 = 0;
            double lastSm3 = 0;
            double lastSa3 = 0;
            for (int i = 0; i < ticks.size(); i++)
            {
                double c = ticks[i];
                double m = Math.Max(c - lastClosePx, 0);
                double a = Math.Abs(c - lastClosePx);
                if (i == 0)
                {
                    lastSm1 = 0;
                    lastSa1 = 0;
                    rsi1.add(0);
                }
                else
                {
                    lastSm1 = (m + (n1 - 1) * lastSm1) / n1;
                    lastSa1 = (a + (n1 - 1) * lastSa1) / n1;
                    if (lastSa1 != 0)
                    {
                        rsi1.add(lastSm1 / lastSa1 * 100);
                    }
                    else
                    {
                        rsi1.add(0);
                    }
                }
                if (i == 0)
                {
                    lastSm2 = 0;
                    lastSa2 = 0;
                    rsi2.add(0);
                }
                else
                {
                    lastSm2 = (m + (n2 - 1) * lastSm2) / n2;
                    lastSa2 = (a + (n2 - 1) * lastSa2) / n2;
                    if (lastSa2 != 0)
                    {
                        rsi2.add(lastSm2 / lastSa2 * 100);
                    }
                    else
                    {
                        rsi2.add(0);
                    }
                }
                if (i == 0)
                {
                    lastSm3 = 0;
                    lastSa3 = 0;
                    rsi3.add(0);
                }
                else
                {
                    lastSm3 = (m + (n3 - 1) * lastSm3) / n3;
                    lastSa3 = (a + (n3 - 1) * lastSa3) / n3;
                    if (lastSa3 != 0)
                    {
                        rsi3.add(lastSm3 / lastSa3 * 100);
                    }
                    else
                    {
                        rsi3.add(0.0);
                    }
                }
                lastClosePx = c;
            }
        }

        /// <summary>
        /// 计算ROC数据
        /// </summary>
        public virtual void getRocData(ArrayList<double> ticks, int n, int m, ArrayList<double> roc, ArrayList<double> maroc)
        {
            for (int i = 0; i < ticks.size(); i++)
            {
                double currRoc = 0;
                if (i >= n)
                {
                    currRoc = 100 * (ticks[i] - ticks[i - n]) / ticks[i - n];
                    roc.add(currRoc);
                }
                else
                {
                    currRoc = 100 * (ticks[i] - ticks[0]) / ticks[0];
                    roc.add(currRoc);
                }
            }
            ArrayList<double> marocMA = maValue(roc, m);
            for (int i = 0; i < marocMA.size(); i++)
            {
                maroc.add(marocMA[i]);
            }
        }

        /// <summary>
        /// 获取BIAS的数据
        /// </summary>
        public virtual void getBIASData(ArrayList<double> ticks, int n1, int n2, int n3, ArrayList<double> bias1Arr, ArrayList<double> bias2Arr, ArrayList<double> bias3Arr)
        {
            ArrayList<double> ma1 = maValue(ticks, n1);
            ArrayList<double> ma2 = maValue(ticks, n2);
            ArrayList<double> ma3 = maValue(ticks, n3);
            for (int i = 0; i < ticks.size(); i++)
            {
                double b1 = (ticks[i] - ma1[i]) / ma1[i] * 100;
                double b2 = (ticks[i] - ma2[i]) / ma2[i] * 100;
                double b3 = (ticks[i] - ma3[i]) / ma3[i] * 100;
                bias1Arr.add(b1);
                bias2Arr.add(b2);
                bias3Arr.add(b3);
            }
        }

        /// <summary>
        /// 计算DMA（平均差）
        /// </summary>
        public virtual void getDMAData(ArrayList<double> ticks, int n1, int n2, ArrayList<double> difArr, ArrayList<double> difmaArr)
        {
            ArrayList<double> ma10 = maValue(ticks, n1);
            ArrayList<double> ma50 = maValue(ticks, n2);
            for (int i = 0; i < ticks.size(); i++)
            {
                double dif = ma10[i] - ma50[i];
                difArr.add(dif);
            }
            ArrayList<double> difma = maValue(difArr, n1);
            for (int i = 0; i < difma.size(); i++)
            {
                difmaArr.add(difma[i]);
            }
        }

        /// <summary>
        /// 计算BBI(多空指标)
        /// </summary>
        public virtual void getBBIData(ArrayList<double> ticks, int n1, int n2, int n3, int n4, ArrayList<double> bbiArr)
        {
            ArrayList<double> ma3 = maValue(ticks, n1);
            ArrayList<double> ma6 = maValue(ticks, n2);
            ArrayList<double> ma12 = maValue(ticks, n3);
            ArrayList<double> ma24 = maValue(ticks, n4);
            for (int i = 0; i < ticks.size(); i++)
            {
                double bbi = (ma3[i] + ma6[i] + ma12[i] + ma24[i]) / 4;
                bbiArr.add(bbi);
            }
        }

        /// <summary>
        /// 计算WR(威廉指标)
        /// </summary>
        public virtual void getWRData(ArrayList<double> highArr, ArrayList<double> lowArr, ArrayList<double> closeArr, int n1, int n2, ArrayList<double> wr1Arr, ArrayList<double> wr2Arr)
        {
            ArrayList<double> highArr1 = hhvValue(highArr, n1);
            ArrayList<double> highArr2 = hhvValue(highArr, n2);
            ArrayList<double> lowArr1 = llvValue(lowArr, n1);
            ArrayList<double> lowArr2 = llvValue(lowArr, n2);
            for (int i = 0; i < closeArr.size(); i++)
            {
                double high1 = highArr1[i];
                double low1 = lowArr1[i];
                double high2 = highArr2[i];
                double low2 = lowArr2[i];
                double close = closeArr[i];
                double wr1 = 100 * (high1 - close) / (high1 - low1);
                double wr2 = 100 * (high2 - close) / (high2 - low2);
                wr1Arr.add(wr1);
                wr2Arr.add(wr2);
            }
        }

        /// <summary>
        /// CCI(顺势指标)计算  CCI（N日）=（TP－MA）÷MD÷0.015
        /// </summary>
        public virtual void getCCIData(ArrayList<double> highArr, ArrayList<double> lowArr, ArrayList<double> closeArr, int n, ArrayList<double> cciArr)
        {
            ArrayList<double> tpArr = new ArrayList<double>();
            for (int i = 0; i < closeArr.size(); i++)
            {
                tpArr.add((closeArr[i] + highArr[i] + lowArr[i]) / 3);
            }
            ArrayList<double> maClose = maValue(closeArr, n);

            ArrayList<double> mdArr = new ArrayList<double>();
            for (int i = 0; i < closeArr.size(); i++)
            {
                mdArr.add(maClose[i] - closeArr[i]);
            }
            ArrayList<double> maMD = maValue(mdArr, n);
            for (int i = 0; i < closeArr.size(); i++)
            {
                double cci = 0;
                if (maMD[i] > 0)
                {
                    cci = (tpArr[i] - maClose[i]) / (maMD[i] * 0.015);
                }
                cciArr.add(cci);
            }
        }

        /// <summary>
        /// 根据索引获取横坐标
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns></returns>
        public virtual int getChartX(int index)
        {
            return (int)(m_leftVScaleWidth +
                (index - m_firstVisibleIndex) * m_hScalePixel +
                m_hScalePixel / 2 + m_offsetX);
        }

        /// <summary>
        /// 获取最大显示记录条数
        /// </summary>
        /// <param name="hScalePixel">间隔</param>
        /// <param name="pureH">横向距离</param>
        /// <returns></returns>
        public virtual int getChartMaxVisibleCount(double hScalePixel, double pureH)
        {
            int count = (int)(pureH / hScalePixel);
            if (count < 0)
            {
                count = 0;
            }
            return count;
        }

        /// <summary>
        /// 获取图表层的高度
        /// </summary>
        /// <returns></returns>
        public virtual int getCandleDivHeight()
        {
            int height = getSize().cy - m_hScaleHeight;
            if (height > 0)
            {
                return (int)(height * m_candleDivPercent);
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取成交量层的高度
        /// </summary>
        /// <returns></returns>
        public virtual int getVolDivHeight()
        {
            int height = getSize().cy - m_hScaleHeight;
            if (height > 0)
            {
                return (int)(height * m_volDivPercent);
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取指标层的高度
        /// </summary>
        /// <returns></returns>
        public virtual int getIndDivHeight()
        {
            int height = getSize().cy - m_hScaleHeight;
            if (height > 0)
            {
                return (int)(height * m_indDivPercent);
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取指标层2的高度
        /// </summary>
        /// <returns></returns>
        public virtual int getIndDivHeight2()
        {
            int height = getSize().cy - m_hScaleHeight;
            if (height > 0)
            {
                return (int)(height * m_indDivPercent2);
            }
            else
            {
                return 0;
            }
        }

        /// <summary>
        /// 获取横向工作区
        /// </summary>
        /// <returns></returns>
        public virtual int getChartWorkAreaWidth()
        {
            return getSize().cx - m_leftVScaleWidth - m_rightVScaleWidth - m_rightSpace - (int)m_offsetX;
        }

        /// <summary>
        /// 计算线性回归上下限
        /// </summary>
        /// <param name="plot">画线</param>
        /// <param name="a">直线k</param>
        /// <param name="b">直线b</param>
        public virtual void getLRBandRange(FCPlot plot, double a, double b)
        {
            int bIndex = getChartIndexByDate(plot.m_key1);
            int eIndex = getChartIndexByDate(plot.m_key2);
            int tempBIndex = Math.Min(bIndex, eIndex);
            int tempEIndex = Math.Max(bIndex, eIndex);
            bIndex = tempBIndex;
            eIndex = tempEIndex;
            ArrayList<double> upList = new ArrayList<double>();
            ArrayList<double> downList = new ArrayList<double>();
            for (int i = bIndex; i <= eIndex; i++)
            {
                double high = m_datas[i].m_high;
                double low = m_datas[i].m_low;
                double midValue = (i - bIndex + 1) * a + b;
                upList.add(high - midValue);
                downList.add(midValue - low);
            }
            m_upSubValue = maxValue(upList);
            m_downSubValue = maxValue(downList);
        }

        /// <summary>
        /// 计算数值在层中的位置
        /// </summary>
        /// <param name="divIndex">所在层</param>
        /// <param name="value">数值</param>
        /// <returns></returns>
        public virtual int getChartY(int divIndex, double value)
        {
            if (divIndex == 0)
            {
                if (m_candleMax > m_candleMin)
                {
                    double cValue = value, cMax = m_candleMax, cMin = m_candleMin;
                    if (m_vScaleType != "standard")
                    {
                        if (cValue > 0)
                        {
                            cValue = Math.Log(cValue);
                        }
                        else if (cValue < 0)
                        {
                            cValue = -Math.Log(Math.Abs(cValue));
                        }
                        if (cMax > 0)
                        {
                            cMax = Math.Log(cMax);
                        }
                        else if (cMax < 0)
                        {
                            cMax = -Math.Log(Math.Abs(cMax));
                        }
                        if (cMin > 0)
                        {
                            cMin = Math.Log(cMin);
                        }
                        else if (cMin < 0)
                        {
                            cMin = -Math.Log(Math.Abs(cMin));
                        }
                    }
                    double rate = (cValue - cMin) / (cMax - cMin);
                    int divHeight = getCandleDivHeight();
                    return (int)(divHeight - m_candlePaddingBottom - (divHeight - m_candlePaddingTop - m_candlePaddingBottom) *
                            rate);
                }
                else
                {
                    return 0;
                }
            }
            else if (divIndex == 1)
            {
                if (m_volMax > m_volMin)
                {
                    double rate = (value - m_volMin) / (m_volMax - m_volMin);
                    int candleHeight = getCandleDivHeight();
                    int volHeight = getVolDivHeight();
                    return (int)(candleHeight + volHeight - m_volPaddingBottom - (volHeight - m_volPaddingTop - m_volPaddingBottom) * rate);
                }
                else
                {
                    return 0;
                }
            }
            else if (divIndex == 2)
            {
                if (m_indMax > m_indMin)
                {
                    double rate = (value - m_indMin) / (m_indMax - m_indMin);
                    int candleHeight = getCandleDivHeight();
                    int volHeight = getVolDivHeight();
                    int indHeight = getIndDivHeight();
                    return (int)(candleHeight + volHeight + indHeight - m_indPaddingBottom - (indHeight - m_indPaddingTop - m_indPaddingBottom) * rate);
                }
                else
                {
                    return 0;
                }
            }
            else if (divIndex == 3)
            {
                if (m_indMax2 > m_indMin2)
                {
                    double rate = (value - m_indMin2) / (m_indMax2 - m_indMin2);
                    int candleHeight = getCandleDivHeight();
                    int volHeight = getVolDivHeight();
                    int indHeight = getIndDivHeight();
                    int indHeight2 = getIndDivHeight2();
                    return (int)(candleHeight + volHeight + indHeight + indHeight2 - m_indPaddingBottom2 - (indHeight2 - m_indPaddingTop2 - m_indPaddingBottom2) * rate);
                }
                else
                {
                    return 0;
                }
            }
            return 0;
        }

        /// <summary>
        /// 根据位置计算索引
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <returns></returns>
        public virtual int getChartIndex(FCPoint mp)
        {
            if (m_datas.size() == 0)
            {
                return -1;
            }
            if (mp.x <= 0)
            {
                return 0;
            }
            double intX = mp.x - m_leftVScaleWidth - m_hScalePixel - m_offsetX;
if (intX < 0)
            {
                intX = 0;
            }
            int index = (int)(m_firstVisibleIndex + intX / m_hScalePixel);
            int intPixel = (int)m_hScalePixel;
            if (intPixel > 0 && intX % intPixel != 0)
            {
                index++;
            }
            if (index < 0)
            {
                index = 0;
            }
            else if (index > m_datas.size() - 1)
            {
                index = m_datas.size() - 1;
            }
            return index;
        }

        /// <summary>
        /// 根据索引获取日期
        /// </summary>
        /// <param name="index">索引</param>
        /// <returns></returns>
        public virtual double getChartDateByIndex(int index)
        {
            double date = 0;
            if (index >= 0 && index < m_datas.size())
            {
                date = m_datas[index].m_date;
            }
            return date;
        }

        /// <summary>
        /// 根据坐标获取对应的值
        /// </summary>
        /// <param name="point">坐标</param>
        /// <returns></returns>
        public virtual double getChartValue(FCPoint point)
        {
            double candleHeight = getCandleDivHeight();
            double volHeight = getVolDivHeight();
            double indHeight = getIndDivHeight();
            double indHeight2 = getIndDivHeight();
            if (point.y <= candleHeight)
            {
                if (candleHeight - m_candlePaddingTop - m_candlePaddingBottom > 0)
                {
                    double rate = (candleHeight - m_candlePaddingBottom - point.y) /
                        (candleHeight - m_candlePaddingTop - m_candlePaddingBottom);
                    double cMin = m_candleMin, cMax = m_candleMax;
                    if (m_vScaleType != "standard")
                    {
                        if (cMax > 0)
                        {
                            cMax = Math.Log(cMax);
                        }
                        else if (cMax < 0)
                        {
                            cMax = -Math.Log(Math.Abs(cMax));
                        }
                        if (cMin > 0)
                        {
                            cMin = Math.Log(cMin);
                        }
                        else if (cMin < 0)
                        {
                            cMin = -Math.Log(Math.Abs(cMin));
                        }
                    }
                    double result = cMin + (cMax - cMin) * rate;
                    if (m_vScaleType != "standard")
                    {
                        return Math.Pow(10, result);
                    }
                    else
                    {
                        return result;
                    }
                }
            }
            else if (point.y > candleHeight && point.y <= candleHeight + volHeight)
            {
                if (volHeight - m_volPaddingTop - m_volPaddingBottom > 0)
                {
                    double rate =
                        (volHeight - m_volPaddingBottom - (point.y - candleHeight)) /
                            (volHeight - m_volPaddingTop - m_volPaddingBottom);
                    return m_volMin + (m_volMax - m_volMin) * rate;
                }
            }
            else if (point.y > candleHeight + volHeight &&
              point.y <= candleHeight + volHeight + indHeight)
            {
                if (indHeight - m_indPaddingTop - m_indPaddingBottom > 0)
                {
                    double rate = (indHeight -
                            m_indPaddingBottom -
                            (point.y - candleHeight - volHeight)) /
                        (indHeight - m_indPaddingTop - m_indPaddingBottom);
                    return m_indMin + (m_indMax - m_indMin) * rate;
                }
            }
            else if (point.y > candleHeight + volHeight + indHeight &&
              point.y <= candleHeight + volHeight + indHeight + indHeight2)
            {
                if (indHeight2 - m_indPaddingTop2 - m_indPaddingBottom2 > 0)
                {
                    double rate = (indHeight2 -
                            m_indPaddingBottom2 -
                            (point.y - candleHeight - volHeight - indHeight)) /
                        (indHeight2 - m_indPaddingTop2 - m_indPaddingBottom2);
                    return m_indMin2 + (m_indMax2 - m_indMin2) * rate;
                }
            }
            return 0;
        }

        /// <summary>
        /// 计算数值在层中的右轴位置
        /// </summary>
        /// <param name="divIndex">所在层</param>
        /// <param name="value">数值</param>
        /// <returns></returns>
        public virtual int getChartYInRight(int divIndex, double value)
        {
            if (divIndex == 0)
            {
                if (m_candleMaxRight > m_candleMinRight)
                {
                    double cValue = value,
                        cMax = m_candleMaxRight,
                        cMin = m_candleMinRight;
                    if (m_vScaleType != "standard")
                    {
                        if (cValue > 0)
                        {
                            cValue = Math.Log(cValue);
                        }
                        else if (cValue < 0)
                        {
                            cValue = -Math.Log(Math.Abs(cValue));
                        }
                        if (cMax > 0)
                        {
                            cMax = Math.Log(cMax);
                        }
                        else if (cMax < 0)
                        {
                            cMax = -Math.Log(Math.Abs(cMax));
                        }
                        if (cMin > 0)
                        {
                            cMin = Math.Log(cMin);
                        }
                        else if (cMin < 0)
                        {
                            cMin = -Math.Log(Math.Abs(cMin));
                        }
                    }
                    double rate = (cValue - cMin) / (cMax - cMin);
                    int divHeight = getCandleDivHeight();
                    return (int)(divHeight - m_candlePaddingBottom - (divHeight - m_candlePaddingTop - m_candlePaddingBottom) * rate);
                }
                else
                {
                    return 0;
                }
            }
            else if (divIndex == 1)
            {
                if (m_volMaxRight > m_volMinRight)
                {
                    double rate = (value - m_volMinRight) / (m_volMaxRight - m_volMinRight);
                    int candleHeight = getCandleDivHeight();
                    int volHeight = getVolDivHeight();
                    return (int)(candleHeight + volHeight - m_volPaddingBottom - (volHeight - m_volPaddingTop - m_volPaddingBottom) * rate);
                }
                else
                {
                    return 0;
                }
            }
            else if (divIndex == 2)
            {
                if (m_indMaxRight > m_indMinRight)
                {
                    double rate = (value - m_indMinRight) / (m_indMaxRight - m_indMinRight);
                    int candleHeight = getCandleDivHeight();
                    int volHeight = getVolDivHeight();
                    int indHeight = getIndDivHeight();
                    return (int)(candleHeight + volHeight + indHeight - m_indPaddingBottom - (indHeight - m_indPaddingTop - m_indPaddingBottom) * rate);
                }
                else
                {
                    return 0;
                }
            }
            else if (divIndex == 3)
            {
                if (m_indMax2Right > m_indMin2Right)
                {
                    double rate = (value - m_indMin2Right) / (m_indMax2Right - m_indMin2Right);
                    int candleHeight = getCandleDivHeight();
                    int volHeight = getVolDivHeight();
                    int indHeight = getIndDivHeight();
                    int indHeight2 = getIndDivHeight2();
                    return (int)(candleHeight + volHeight + indHeight + indHeight2 - m_indPaddingBottom2 - (indHeight2 - m_indPaddingTop2 - m_indPaddingBottom2) * rate);
                }
                else
                {
                    return 0;
                }
            }
            return 0;
        }

        /// <summary>
        /// 根据坐标获取对应的值
        /// </summary>
        /// <param name="point">坐标</param>
        /// <returns></returns>
        public virtual double getCandleDivValue(FCPoint point)
        {
            double candleHeight = getCandleDivHeight();
            double rate = 0;
            if (candleHeight - m_candlePaddingTop - m_candlePaddingBottom > 0)
            {
                rate = (candleHeight - m_candlePaddingBottom - point.y) /
                     (candleHeight - m_candlePaddingTop - m_candlePaddingBottom);
            }
            double cMin = m_candleMin, cMax = m_candleMax;
            if (m_vScaleType != "standard")
            {
                if (cMax > 0)
                {
                    cMax = Math.Log(cMax);
                }
                else if (cMax < 0)
                {
                    cMax = -Math.Log(Math.Abs(cMax));
                }
                if (cMin > 0)
                {
                    cMin = Math.Log(cMin);
                }
                else if (cMin < 0)
                {
                    cMin = -Math.Log(Math.Abs(cMin));
                }
            }
            double result = cMin + (cMax - cMin) * rate;
            if (m_vScaleType != "standard")
            {
                return Math.Pow(10, result);
            }
            else
            {
                return result;
            }
        }

        /// <summary>
        /// 计算最大值
        /// </summary>
        /// <param name="ticks">最高价数组</param>
        /// <param name="days">周期</param>
        /// <returns></returns>
        public virtual ArrayList<double> hhvValue(ArrayList<double> ticks, int days)
        {
            ArrayList<double> hhv = new ArrayList<double>();
            double max = ticks[0];
            for (int i = 0; i < ticks.size(); i++)
            {
                if (i >= days)
                {
                    max = ticks[i];
                    for (int j = i; j > i - days; j--)
                    {
                        if (max < ticks[j])
                        {
                            max = ticks[j];
                        }
                    }
                    hhv.add(max);
                }
                else
                {
                    if (max < ticks[i])
                    {
                        max = ticks[i];
                    }
                    hhv.add(max);
                }
            }
            return hhv;
        }

        /// <summary>
        /// 图表的键盘按下事件
        /// </summary>
        /// <param name="key">按键</param>
        public void keyDownChart(char key)
        {
            if (key == 38)
            {
                zoomOutChart();
            }
            else if (key == 40)
            {
                zoomInChart();
            }
            else if (key == 37)
            {
                scrollLeftChart(1);
            }
            else if (key == 39)
            {
                scrollRightChart(1);
            }
        }

        /// <summary>
        /// 判断是否选中图形
        /// </summary>
        /// <param name="mp">坐标</param>
        public virtual void judgeSelectShape(FCPoint mp)
        {
            m_selectShape = "";
            m_selectShapeEx = "";
            double candleHeight = getCandleDivHeight();
            double volHeight = getVolDivHeight();
            double indHeight = getIndDivHeight();
            double indHeight2 = getIndDivHeight2();
            int index = getChartIndex(mp);
            if (mp.y >= candleHeight + volHeight + indHeight &&
                mp.y <= candleHeight + volHeight + indHeight + indHeight2)
            {
                if (m_showIndicator2 == "MACD")
                {
                    if (selectLines(mp, 3, m_allmacdarr, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "MACD";
                    }
                    if (selectLines(mp, 3, m_alldifarr, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "DIF";
                    }
                    else if (selectLines(mp, 3, m_alldeaarr, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "DEA";
                    }
                }
                else if (m_showIndicator2 == "KDJ")
                {
                    if (selectLines(mp, 3, m_kdjK, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "K";
                    }
                    else if (selectLines(mp, 3, m_kdjD, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "D";
                    }
                    else if (selectLines(mp, 3, m_kdjJ, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "J";
                    }
                }
                else if (m_showIndicator2 == "RSI")
                {
                    if (selectLines(mp, 3, m_rsi1, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "6";
                    }
                    else if (selectLines(mp, 3, m_rsi2, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "12";
                    }
                    else if (selectLines(mp, 3, m_rsi3, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "24";
                    }
                }
                else if (m_showIndicator2 == "BIAS")
                {
                    if (selectLines(mp, 3, m_bias1, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "1";
                    }
                    else if (selectLines(mp, 3, m_bias2, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "2";
                    }
                    else if (selectLines(mp, 3, m_bias3, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "3";
                    }
                }
                else if (m_showIndicator2 == "ROC")
                {
                    if (selectLines(mp, 3, m_roc, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "ROC";
                    }
                    else if (selectLines(mp, 3, m_rocMa, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "ROCMA";
                    }
                }
                else if (m_showIndicator2 == "WR")
                {
                    if (selectLines(mp, 3, m_wr1, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "1";
                    }
                    else if (selectLines(mp, 3, m_wr2, index))
                    {
                        m_selectShape = "WR";
                        m_selectShapeEx = "2";
                    }
                }
                else if (m_showIndicator2 == "CCI")
                {
                    if (selectLines(mp, 3, m_cci, index))
                    {
                        m_selectShape = m_showIndicator2;
                    }
                }
                else if (m_showIndicator2 == "BBI")
                {
                    if (selectLines(mp, 3, m_bbi, index))
                    {
                        m_selectShape = m_showIndicator2;
                    }
                }
                else if (m_showIndicator2 == "TRIX")
                {
                    if (selectLines(mp, 3, m_trix, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "TRIX";
                    }
                    else if (selectLines(mp, 3, m_trixMa, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "TRIXMA";
                    }
                }
                else if (m_showIndicator2 == "DMA")
                {
                    if (selectLines(mp, 3, m_dma1, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "DIF";
                    }
                    else if (selectLines(mp, 3, m_dma2, index))
                    {
                        m_selectShape = m_showIndicator2;
                        m_selectShapeEx = "DIFMA";
                    }
                }
            }
            else if (mp.y >= candleHeight + volHeight &&
                mp.y <= candleHeight + volHeight + indHeight)
            {
                if (m_showIndicator == "MACD")
                {
                    if (selectLines(mp, 2, m_allmacdarr, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "MACD";
                    }
                    if (selectLines(mp, 2, m_alldifarr, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "DIF";
                    }
                    else if (selectLines(mp, 2, m_alldeaarr, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "DEA";
                    }
                }
                else if (m_showIndicator == "KDJ")
                {
                    if (selectLines(mp, 2, m_kdjK, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "K";
                    }
                    else if (selectLines(mp, 2, m_kdjD, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "D";
                    }
                    else if (selectLines(mp, 2, m_kdjJ, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "J";
                    }
                }
                else if (m_showIndicator == "RSI")
                {
                    if (selectLines(mp, 2, m_rsi1, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "6";
                    }
                    else if (selectLines(mp, 2, m_rsi2, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "12";
                    }
                    else if (selectLines(mp, 2, m_rsi3, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "24";
                    }
                }
                else if (m_showIndicator == "BIAS")
                {
                    if (selectLines(mp, 2, m_bias1, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "1";
                    }
                    else if (selectLines(mp, 2, m_bias2, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "2";
                    }
                    else if (selectLines(mp, 2, m_bias3, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "3";
                    }
                }
                else if (m_showIndicator == "ROC")
                {
                    if (selectLines(mp, 2, m_roc, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "ROC";
                    }
                    else if (selectLines(mp, 2, m_rocMa, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "ROCMA";
                    }
                }
                else if (m_showIndicator == "WR")
                {
                    if (selectLines(mp, 2, m_wr1, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "1";
                    }
                    else if (selectLines(mp, 2, m_wr2, index))
                    {
                        m_selectShape = "WR";
                        m_selectShapeEx = "2";
                    }
                }
                else if (m_showIndicator == "CCI")
                {
                    if (selectLines(mp, 2, m_cci, index))
                    {
                        m_selectShape = m_showIndicator;
                    }
                }
                else if (m_showIndicator == "BBI")
                {
                    if (selectLines(mp, 2, m_bbi, index))
                    {
                        m_selectShape = m_showIndicator;
                    }
                }
                else if (m_showIndicator == "TRIX")
                {
                    if (selectLines(mp, 2, m_trix, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "TRIX";
                    }
                    else if (selectLines(mp, 2, m_trixMa, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "TRIXMA";
                    }
                }
                else if (m_showIndicator == "DMA")
                {
                    if (selectLines(mp, 2, m_dma1, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "DIF";
                    }
                    else if (selectLines(mp, 2, m_dma2, index))
                    {
                        m_selectShape = m_showIndicator;
                        m_selectShapeEx = "DIFMA";
                    }
                }
            }
            else if (mp.y >= candleHeight && mp.y <= candleHeight + volHeight)
            {
                int volY = getChartY(1, m_datas[index].m_volume);
                int zeroY = getChartY(1, 0);
                if (mp.y >= Math.Min(volY, zeroY) && mp.y <= Math.Max(volY, zeroY))
                {
                    m_selectShape = "VOL";
                }
            }
            else if (mp.y >= 0 && mp.y <= candleHeight)
            {
                bool isTrend = m_cycle == "trend";
                if (!isTrend)
                {
                    if (m_mainIndicator == "BOLL")
                    {
                        if (selectLines(mp, 0, m_bollMid, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "MID";
                        }
                        else if (selectLines(mp, 0, m_bollUp, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "UP";
                        }
                        else if (selectLines(mp, 0, m_bollDown, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "DOWN";
                        }
                    }
                    else if (m_mainIndicator == "MA")
                    {
                        if (selectLines(mp, 0, m_ma5, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "5";
                        }
                        else if (selectLines(mp, 0, m_ma10, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "10";
                        }
                        else if (selectLines(mp, 0, m_ma20, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "20";
                        }
                        else if (selectLines(mp, 0, m_ma30, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "30";
                        }
                        else if (selectLines(mp, 0, m_ma120, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "120";
                        }
                        else if (selectLines(mp, 0, m_ma250, index))
                        {
                            m_selectShape = m_mainIndicator;
                            m_selectShapeEx = "250";
                        }
                    }
                }
                if (m_selectShape == "")
                {
                    int highY = getChartY(0, m_datas[index].m_high);
                    int lowY = getChartY(0, m_datas[index].m_low);
                    if (isTrend)
                    {
                        if (selectLines(mp, 0, m_closeArr, index))
                        {
                            m_selectShape = "CANDLE";
                        }
                    }
                    else
                    {
                        if (mp.y >= Math.Min(lowY, highY) && mp.y <= Math.Max(lowY, highY))
                        {
                            m_selectShape = "CANDLE";
                        }
                    }
                }
            }
            if (m_shapes.size() > 0)
            {
                for (int i = 0; i < m_shapes.size(); i++)
                {
                    BaseShape shape = m_shapes[i];
                    if (shape.m_leftOrRight)
                    {
                        if (selectLines(mp, shape.m_divIndex, shape.m_datas, index))
                        {
                            m_selectShape = shape.m_shapeName;
                            break;
                        }
                    }
                    else
                    {
                        if (selectLinesInRight(mp, shape.m_divIndex, shape.m_datas, index))
                        {
                            m_selectShape = shape.m_shapeName;
                            break;
                        }
                    }
                }
            }
        }

        /// <summary>
        /// 计算直线参数
        /// </summary>
        /// <param name="x1">横坐标1</param>
        /// <param name="y1">纵坐标1</param>
        /// <param name="x2">横坐标2</param>
        /// <param name="y2">纵坐标2</param>
        /// <param name="oX">坐标起始X</param>
        /// <param name="oY">坐标起始Y</param>
        public virtual void lineXY(double x1, double y1, double x2, double y2, double oX, double oY)
        {
            m_kChart = 0;
            m_bChart = 0;
            if ((x1 - oX) != (x2 - oX))
            {
                m_kChart = ((y2 - oY) - (y1 - oY)) / ((x2 - oX) - (x1 - oX));
                m_bChart = (y1 - oY) - m_kChart * (x1 - oX);
            }
        }

        /// <summary>
        /// 计算线性回归
        /// </summary>
        /// <param name="list">集合</param>
        /// <returns></returns>
        public virtual double linearRegressionEquation(ArrayList<double> list)
        {
            double result = 0;
            double sumX = 0;
            double sumY = 0;
            double sumUp = 0;
            double sumDown = 0;
            double xAvg = 0;
            double yAvg = 0;
            m_kChart = 0;
            m_bChart = 0;
            int length = list.size();
            if (length > 1)
            {
                for (int i = 0; i < length; i++)
                {
                    sumX += i + 1;
                    sumY += list[i];
                }
                xAvg = sumX / length;
                yAvg = sumY / length;
                for (int i = 0; i < length; i++)
                {
                    sumUp += (i + 1 - xAvg) * (list[i] - yAvg);
                    sumDown += (i + 1 - xAvg) * (i + 1 - xAvg);
                }
                m_kChart = sumUp / sumDown;
                m_bChart = yAvg - m_kChart * xAvg;
            }
            return result;
        }


        /// <summary>
        /// 计算最小值
        /// </summary>
        /// <param name="ticks">最低价数组</param>
        /// <param name="days">日期</param>
        /// <returns></returns>
        public virtual ArrayList<double> llvValue(ArrayList<double> ticks, int days)
        {
            ArrayList<double> llv = new ArrayList<double>();
            double min = ticks[0];
            for (int i = 0; i < ticks.size(); i++)
            {
                if (i >= days)
                {
                    min = ticks[i];
                    for (int j = i; j > i - days; j--)
                    {
                        if (min > ticks[j])
                        {
                            min = ticks[j];
                        }
                    }
                    llv.add(min);
                }
                else
                {
                    if (min > ticks[i])
                    {
                        min = ticks[i];
                    }
                    llv.add(min);
                }
            }
            return llv;
        }

        /// <summary>
        /// 计算最大值
        /// </summary>
        /// <param name="list">集合</param>
        /// <returns></returns>
        public virtual double maxValue(ArrayList<double> list)
        {
            int length = list.size();
            double max = 0;
            for (int i = 0; i < length; i++)
            {
                if (i == 0)
                {
                    max = list[i];
                }
                else
                {
                    if (max < list[i])
                    {
                        max = list[i];
                    }
                }
            }
            return max;
        }

        /// <summary>
        /// 计算最小值
        /// </summary>
        /// <param name="list">集合</param>
        /// <returns></returns>
        public virtual double minValue(ArrayList<double> list)
        {
            int length = list.size();
            double min = 0;
            for (int i = 0; i < length; i++)
            {
                if (i == 0)
                {
                    min = list[i];
                }
                else
                {
                    if (min > list[i])
                    {
                        min = list[i];
                    }
                }
            }
            return min;
        }

        /// <summary>
        /// MA数据计算
        /// </summary>
        /// <returns></returns>
        public virtual ArrayList<double> maValue(ArrayList<double> ticks, int days)
        {
            double maSum = 0;
            ArrayList<double> mas = new ArrayList<double>();
            double last = 0;
            for (int i = 0; i < ticks.size(); i++)
            {
                double ma = 0;
                if (i >= days)
                {
                    last = ticks[i - days];
                    maSum = maSum + ticks[i] - last;
                    ma = maSum / days;
                }
                else
                {
                    maSum += ticks[i];
                    ma = maSum / (i + 1);
                }
                mas.add(ma);
            }
            return mas;
        }

        /// <summary>
        /// 绘图方法
        /// </summary>
        /// <param name="paint">绘图对象</param>
        /// <param name="clipRect">裁剪区域</param>
        public override void onPaint(FCPaint paint, FCRect clipRect)
        {
            base.onPaint(paint, clipRect);
            drawChartScale(paint, clipRect);
            drawChartStock(paint, clipRect);
            drawChartPlot(paint, clipRect);
            drawChartCrossLine(paint, clipRect);
        }

        /// <summary>
        /// 触摸按下方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchDown(FCTouchInfo touchInfo)
        {
            base.onTouchDown(touchInfo);
            touchDownChart(touchInfo.m_firstTouch, touchInfo.m_firstPoint, touchInfo.m_secondTouch, touchInfo.m_secondPoint, touchInfo.m_clicks);
            invalidate();
        }

        /// <summary>
        /// 触摸移动方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchMove(FCTouchInfo touchInfo)
        {
            base.onTouchMove(touchInfo);
            touchMoveChart(touchInfo.m_firstTouch, touchInfo.m_firstPoint, touchInfo.m_secondTouch, touchInfo.m_secondPoint);
            invalidate();
        }

        /// <summary>
        /// 鼠标离开方法
        /// </summary>
        /// <param name="touchInfo"></param>
        public override void onTouchLeave(FCTouchInfo touchInfo)
        {
            base.onTouchLeave(touchInfo);
            invalidate();
        }

        /// <summary>
        /// 触摸抬起方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchUp(FCTouchInfo touchInfo)
        {
            base.onTouchUp(touchInfo);
            m_firstTouchIndexCache = -1;
            m_secondTouchIndexCache = -1;
            invalidate();
        }

        /// <summary>
        /// 触摸滚动方法
        /// </summary>
        /// <param name="touchInfo">触摸信息</param>
        public override void onTouchWheel(FCTouchInfo touchInfo)
        {
            base.onTouchWheel(touchInfo);
            if (touchInfo.m_delta > 0)
            {
                zoomOutChart();
            }
            else if (touchInfo.m_delta < 0)
            {
                zoomInChart();
            }
            invalidate();
        }

        /// <summary>
        /// 键盘按下方法
        /// </summary>
        /// <param name="key">按键</param>
        public override void onKeyDown(char key)
        {
            base.onKeyDown(key);
            keyDownChart(key);
            invalidate();
        }

        /// <summary>
        /// 计算平行四边形参数
        /// </summary>
        /// <param name="x1">横坐标1</param>
        /// <param name="y1">纵坐标1</param>
        /// <param name="x2">横坐标2</param>
        /// <param name="y2">纵坐标2</param>
        /// <param name="x3">横坐标3</param>
        /// <param name="y3">纵坐标3</param>
        public virtual void parallelogram(double x1, double y1, double x2, double y2, double x3, double y3)
        {
            m_x4Chart = x1 + x3 - x2;
            m_y4Chart = y1 + y3 - y2;
        }

        /// <summary>
        /// 根据坐标计算矩形
        /// </summary>
        /// <param name="x1">横坐标1</param>
        /// <param name="y1">纵坐标1</param>
        /// <param name="x2">横坐标2</param>
        /// <param name="y2">纵坐标2</param>
        public virtual void rectangleXYWH(double x1, double y1, double x2, double y2)
        {
            m_xChart = x1 < x2 ? x1 : x2;
            m_yChart = y1 < y2 ? y1 : y2;
            m_wChart = x1 - x2 > 0 ? x1 - x2 : x2 - x1;
            m_hChart = y1 - y2 > 0 ? y1 - y2 : y2 - y1;
            if (m_wChart <= 0)
            {
                m_wChart = 4;
            }
            if (m_hChart <= 0)
            {
                m_hChart = 4;
            }
        }

        /// <summary>
        /// 自动设置首先可见和最后可见的记录号
        /// </summary>
        public virtual void resetChartVisibleRecord()
        {
            int rowsCount = m_datas.size();
            double workingAreaWidth = getChartWorkAreaWidth();
            if (m_autoFillHScale)
            {
                if (workingAreaWidth > 0 && rowsCount > 0)
                {
                    m_hScalePixel = workingAreaWidth / rowsCount;
                    m_firstVisibleIndex = 0;
                    m_lastVisibleIndex = rowsCount - 1;
                }
            }
            else
            {
                int maxVisibleRecord =
                    getChartMaxVisibleCount(m_hScalePixel, workingAreaWidth);
                //没数据时重置
                if (rowsCount == 0)
                {
                    m_firstVisibleIndex = -1;
                    m_lastVisibleIndex = -1;
                }
                else
                {
                    //数据不足一屏时
                    if (rowsCount < maxVisibleRecord)
                    {
                        m_lastVisibleIndex = rowsCount - 1;
                        m_firstVisibleIndex = 0;
                    }
                    //数据超过一屏时
                    else
                    {
                        //显示中间的数据时
                        if (m_firstVisibleIndex != -1 &&
                            m_lastVisibleIndex != -1 &&
                            !m_lastRecordIsVisible)
                        {
                            int index = getChartIndexByDate(m_lastVisibleKey);
                            if (index != -1)
                            {
                                m_lastVisibleIndex = index;
                            }
                            m_firstVisibleIndex =
                                m_lastVisibleIndex - maxVisibleRecord + 1;
                            if (m_firstVisibleIndex < 0)
                            {
                                m_firstVisibleIndex = 0;
                                m_lastVisibleIndex = m_firstVisibleIndex + maxVisibleRecord;
                                checkChartLastVisibleIndex();
                            }
                        }
                        else
                        {
                            //第一条或最后一条数据被显示时
                            m_lastVisibleIndex = rowsCount - 1;
                            m_firstVisibleIndex =
                                m_lastVisibleIndex - maxVisibleRecord + 1;
                            if (m_firstVisibleIndex > m_lastVisibleIndex)
                            {
                                m_firstVisibleIndex = m_lastVisibleIndex;
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// REF函数
        /// </summary>
        /// <param name="ticks">数据</param>
        /// <param name="days">日期</param>
        /// <returns></returns>
        public virtual ArrayList<double> refValue(ArrayList<double> ticks, int days)
        {
            ArrayList<double> refArr = new ArrayList<double>();
            int length = ticks.size();
            for (int i = 0; i < length; i++)
            {
                double refV = 0;
                if (i >= days)
                {
                    refV = ticks[i - days];
                }
                else
                {
                    refV = ticks[0];
                }
                refArr.add(refV);
            }
            return refArr;
        }

        /// <summary>
        /// 判断是否选中直线
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <param name="x1">横坐标1</param>
        /// <param name="y1">纵坐标1</param>
        /// <param name="x2">横坐标2</param>
        /// <param name="y2">纵坐标2</param>
        /// <returns>状态</returns>
        public virtual bool selectLine(FCPoint mp, double x1, double y1, double x2, double y2)
        {
            lineXY(x1, y1, x2, y2, 0, 0);
            if (!(m_kChart == 0 && m_bChart == 0))
            {
                if (mp.y / (mp.x * m_kChart + m_bChart) >= 0.9 &&
                    mp.y / (mp.x * m_kChart + m_bChart) <= 1.1)
                {
                    return true;
                }
            }
            else
            {
                if (mp.x >= x1 - m_plotPointSizeChart &&
                    mp.x <= x1 + m_plotPointSizeChart)
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// 判断是否选中射线
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <param name="x1">横坐标1</param>
        /// <param name="y1">纵坐标1</param>
        /// <param name="x2">横坐标2</param>
        /// <param name="y2">纵坐标2</param>
        /// <returns>状态</returns>
        public virtual bool selectRay(FCPoint mp, double x1, double y1, double x2, double y2)
        {
            lineXY(x1, y1, x2, y2, 0, 0);
            if (!(m_kChart == 0 && m_bChart == 0))
            {
                if (mp.y / (mp.x * m_kChart + m_bChart) >= 0.9 &&
                    mp.y / (mp.x * m_kChart + m_bChart) <= 1.1)
                {
                    if (x1 >= x2)
                    {
                        if (mp.x > x1 + m_plotPointSizeChart)
                        {
                            return false;
                        }
                    }
                    else if (x1 < x2)
                    {
                        if (mp.x < x1 - m_plotPointSizeChart)
                        {
                            return false;
                        }
                    }
                    return true;
                }
            }
            else
            {
                if (mp.x >= x1 - m_plotPointSizeChart &&
                    mp.x <= x1 + m_plotPointSizeChart)
                {
                    if (y1 >= y2)
                    {
                        if (mp.y <= y1 - m_plotPointSizeChart)
                        {
                            return true;
                        }
                    }
                    else
                    {
                        if (mp.y >= y1 - m_plotPointSizeChart)
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 判断是否选中线段
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <param name="x1">横坐标1</param>
        /// <param name="y1">纵坐标1</param>
        /// <param name="x2">横坐标2</param>
        /// <param name="y2">纵坐标2</param>
        /// <returns></returns>
        public virtual bool selectSegment(FCPoint mp, double x1, double y1, double x2, double y2)
        {
            lineXY(x1, y1, x2, y2, 0, 0);
            double smallX = x1 <= x2 ? x1 : x2;
            double smallY = y1 <= y2 ? y1 : y2;
            double bigX = x1 > x2 ? x1 : x2;
            double bigY = y1 > y2 ? y1 : y2;
            if (mp.x >= smallX - 2 &&
                mp.x <= bigX + 2 &&
                mp.y >= smallY - 2 &&
                mp.y <= bigY + 2)
            {
                if (m_kChart != 0 || m_bChart != 0)
                {
                    if (mp.y / (mp.x * m_kChart + m_bChart) >= 0.9 &&
                        mp.y / (mp.x * m_kChart + m_bChart) <= 1.1)
                    {
                        return true;
                    }
                }
                else
                {
                    if (mp.x >= x1 - m_plotPointSizeChart &&
                        mp.x <= x1 + m_plotPointSizeChart)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 获取方差数据
        /// </summary>
        /// <returns></returns>
        public virtual double standardDeviationSum(ArrayList<double> listValue, double avgValue)
        {
            double targetValue = listValue[listValue.size() - 1];
            double sumValue = (targetValue - avgValue) * (targetValue - avgValue);
            for (int i = 0; i < listValue.size() - 1; i++)
            {
                double ileft = listValue[i];
                sumValue = sumValue + (ileft - avgValue) * (ileft - avgValue);
            }
            return sumValue;
        }

        /// <summary>
        /// 选中画线
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <returns></returns>
        public virtual FCPlot selectPlot(FCPoint mp)
        {
            FCPlot sPlot = null;
            m_startMovePlot = false;
            m_selectPlotPoint = -1;
            for (int i = 0; i < m_plots.size(); i++)
            {
                FCPlot plot = m_plots[i];
                int index1 = 0, index2 = 0, index3 = 0;
                int mpx1 = 0, mpy1 = 0, mpx2 = 0, mpy2 = 0, mpx3 = 0, mpy3 = 0;
                //检查关键点
                if (plot.m_key1 > 0)
                {
                    index1 = getChartIndexByDate(plot.m_key1);
                    mpx1 = getChartX(index1);
                    mpy1 = getChartY(0, plot.m_value1);
                    if (mp.x >= mpx1 - m_plotPointSizeChart &&
                        mp.x <= mpx1 + m_plotPointSizeChart &&
                        mp.y >= mpy1 - m_plotPointSizeChart &&
                        mp.y <= mpy1 + m_plotPointSizeChart)
                    {
                        sPlot = plot;
                        m_selectPlotPoint = 0;
                        break;
                    }
                }
                if (plot.m_key2 > 0)
                {
                    index2 = getChartIndexByDate(plot.m_key2);
                    mpx2 = getChartX(index2);
                    mpy2 = getChartY(0, plot.m_value2);
                    if (mp.x >= mpx2 - m_plotPointSizeChart &&
                        mp.x <= mpx2 + m_plotPointSizeChart &&
                        mp.y >= mpy2 - m_plotPointSizeChart &&
                        mp.y <= mpy2 + m_plotPointSizeChart)
                    {
                        sPlot = plot;
                        m_selectPlotPoint = 1;
                        break;
                    }
                }
                if (plot.m_key3 > 0)
                {
                    index3 = getChartIndexByDate(plot.m_key3);
                    mpx3 = getChartX(index3);
                    mpy3 = getChartY(0, plot.m_value3);
                    if (mp.x >= mpx3 - m_plotPointSizeChart &&
                        mp.x <= mpx3 + m_plotPointSizeChart &&
                        mp.y >= mpy3 - m_plotPointSizeChart &&
                        mp.y <= mpy3 + m_plotPointSizeChart)
                    {
                        sPlot = plot;
                        m_selectPlotPoint = 2;
                        break;
                    }
                }
                //判断其余部分的选中
                if (m_selectPlotPoint == -1)
                {
                    if (plot.m_plotType == "Line")
                    {
                        m_startMovePlot = selectLine(mp, mpx1, mpy1, mpx2, mpy2);
                    }
                    else if (plot.m_plotType == "ArrowSegment")
                    {
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                    }
                    else if (plot.m_plotType == "AngleLine")
                    {
                        m_startMovePlot = selectLine(mp, mpx1, mpy1, mpx2, mpy2);
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectLine(mp, mpx1, mpy1, mpx3, mpy3);
                        }
                    }
                    else if (plot.m_plotType == "Parallel")
                    {
                        m_startMovePlot = selectLine(mp, mpx1, mpy1, mpx2, mpy2);
                        if (!m_startMovePlot)
                        {
                            lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                            double newB = mpy3 - m_kChart * mpx3;
                            if (mpx2 == mpx1)
                            {
                                if (mp.x >= mpx3 - m_plotPointSizeChart &&
                                    mp.x <= mpx3 + m_plotPointSizeChart)
                                {
                                    m_startMovePlot = true;
                                }
                            }
                            else
                            {
                                double newX1 = m_leftVScaleWidth;
                                double newY1 = newX1 * m_kChart + newB;
                                double newX2 = getSize().cx - m_rightVScaleWidth;
                                double newY2 = newX2 * m_kChart + newB;
                                m_startMovePlot =
                                    selectLine(mp, newX1, newY1, newX2, newY2);
                            }
                        }
                    }
                    else if (plot.m_plotType == "LRLine")
                    {
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                    }
                    else if (plot.m_plotType == "Segment")
                    {
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                    }
                    else if (plot.m_plotType == "Ray")
                    {
                        m_startMovePlot = selectRay(mp, mpx1, mpy1, mpx2, mpy2);
                    }
                    else if (plot.m_plotType == "Triangle")
                    {
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot =
                                selectSegment(mp, mpx2, mpy2, mpx3, mpy3);
                        }
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot =
                                selectSegment(mp, mpx1, mpy1, mpx3, mpy3);
                        }
                    }
                    else if (plot.m_plotType == "SymmetricTriangle")
                    {
                        if (mpx2 != mpx1)
                        {
                            double a = (double)(mpy2 - mpy1) / (double)(mpx2 - mpx1);
                            double b = mpy1 - a * mpx1;
                            double c = -a;
                            double d = mpy3 - c * mpx3;
                            double leftX = m_leftVScaleWidth;
                            double leftY = leftX * a + b;
                            double rightX = getSize().cx - m_rightVScaleWidth;
                            double rightY = rightX * a + b;
                            m_startMovePlot = selectSegment(mp, leftX, leftY, rightX, rightY);
                            if (!m_startMovePlot)
                            {
                                leftY = leftX * c + d;
                                rightY = rightX * c + d;
                                m_startMovePlot = selectSegment(mp, leftX, leftY, rightX, rightY);
                            }
                        }
                        else
                        {
                            double divHeight = getCandleDivHeight();
                            m_startMovePlot = selectSegment(mp, mpx1, 0, mpx1, divHeight);
                            if (!m_startMovePlot)
                            {
                                m_startMovePlot = selectSegment(mp, mpx3, 0, mpx3, divHeight);
                            }
                        }
                    }
                    else if (plot.m_plotType == "Rect")
                    {
                        int sX1 = Math.Min(mpx1, mpx2);
                        int sY1 = Math.Min(mpy1, mpy2);
                        int sX2 = Math.Max(mpx1, mpx2);
                        int sY2 = Math.Max(mpy1, mpy2);
                        m_startMovePlot = selectSegment(mp, sX1, sY1, sX2, sY1);
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX2, sY1, sX2, sY2);
                        }
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX1, sY2, sX2, sY2);
                        }
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX1, sY1, sX1, sY2);
                        }
                    }
                    else if (plot.m_plotType == "BoxLine")
                    {
                        int sX1 = Math.Min(mpx1, mpx2);
                        int sY1 = Math.Min(mpy1, mpy2);
                        int sX2 = Math.Max(mpx1, mpx2);
                        int sY2 = Math.Max(mpy1, mpy2);
                        m_startMovePlot = selectSegment(mp, sX1, sY1, sX2, sY1);
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX2, sY1, sX2, sY2);
                        }
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX1, sY2, sX2, sY2);
                        }
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX1, sY1, sX1, sY2);
                        }
                    }
                    else if (plot.m_plotType == "TironeLevels")
                    {
                        int sX1 = Math.Min(mpx1, mpx2);
                        int sY1 = Math.Min(mpy1, mpy2);
                        int sX2 = Math.Max(mpx1, mpx2);
                        int sY2 = Math.Max(mpy1, mpy2);
                        m_startMovePlot = selectSegment(mp, sX1, sY1, sX2, sY1);
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX1, sY2, sX2, sY2);
                        }
                    }
                    else if (plot.m_plotType == "QuadrantLines")
                    {
                        int sX1 = Math.Min(mpx1, mpx2);
                        int sY1 = Math.Min(mpy1, mpy2);
                        int sX2 = Math.Max(mpx1, mpx2);
                        int sY2 = Math.Max(mpy1, mpy2);
                        m_startMovePlot = selectSegment(mp, sX1, sY1, sX2, sY1);
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot = selectSegment(mp, sX1, sY2, sX2, sY2);
                        }
                    }
                    else if (plot.m_plotType == "GoldenRatio")
                    {
                        int sY1 = Math.Min(mpy1, mpy2);
                        int sY2 = Math.Max(mpy1, mpy2);
                        ArrayList<double> ranges = new ArrayList<double>();
                        ranges.add(0);
                        ranges.add(0.236);
                        ranges.add(0.382);
                        ranges.add(0.5);
                        ranges.add(0.618);
                        ranges.add(0.809);
                        ranges.add(1);
                        ranges.add(1.382);
                        ranges.add(1.618);
                        ranges.add(2);
                        ranges.add(2.382);
                        ranges.add(2.618);
                        for (int j = 0; j < ranges.size(); j++)
                        {
                            double newY = sY1 <= sY2
                                ? sY1 + (sY2 - sY1) * ranges[j]
                                : sY2 + (sY1 - sY2) * (1 - ranges[j]);
                            m_startMovePlot = selectSegment(mp, m_leftVScaleWidth,
                                newY, getSize().cx - m_rightVScaleWidth, newY);
                            if (m_startMovePlot)
                            {
                                break;
                            }
                        }
                    }
                    else if (plot.m_plotType == "Cycle")
                    {
                        double r = Math.Sqrt(
                            Math.Abs((mpx2 - mpx1) * (mpx2 - mpx1) + (mpy2 - mpy1) * (mpy2 - mpy1)));
                        double round =
                            (mp.x - mpx1) * (mp.x - mpx1) + (mp.y - mpy1) * (mp.y - mpy1);
                        if (round / (r * r) >= 0.9 && round / (r * r) <= 1.1)
                        {
                            m_startMovePlot = true;
                        }
                    }
                    else if (plot.m_plotType == "CircumCycle")
                    {
                        ellipseOR(mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
                        double round = (mp.x - m_oXChart) * (mp.x - m_oXChart) +
                            (mp.y - m_oYChart) * (mp.y - m_oYChart);
                        if (round / (m_rChart * m_rChart) >= 0.9 &&
                            round / (m_rChart * m_rChart) <= 1.1)
                        {
                            m_startMovePlot = true;
                        }
                    }
                    else if (plot.m_plotType == "Ellipse")
                    {
                        double x1 = 0, y1 = 0, x2 = 0, y2 = 0;
                        if (mpx1 <= mpx2)
                        {
                            x1 = mpx2;
                            y1 = mpy2;
                            x2 = mpx1;
                            y2 = mpy1;
                        }
                        else
                        {
                            x1 = mpx1;
                            y1 = mpy1;
                            x2 = mpx2;
                            y2 = mpy2;
                        }
                        double x = x1 - (x1 - x2);
                        double y = 0;
                        double width = (x1 - x2) * 2;
                        double height = 0;
                        if (y1 >= y2)
                        {
                            height = (y1 - y2) * 2;
                        }
                        else
                        {
                            height = (y2 - y1) * 2;
                        }
                        y = y2 - height / 2;
                        double a = width / 2;
                        double b = height / 2;
                        m_startMovePlot = ellipseHasPoint(
                            mp.x, mp.y, x + (width / 2), y + (height / 2), a, b);
                    }
                    else if (plot.m_plotType == "LRBand")
                    {
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                        if (!m_startMovePlot)
                        {
                            ArrayList<double> list = new ArrayList<double>();
                            int minIndex = Math.Min(index1, index2);
                            int maxIndex = Math.Max(index1, index2);
                            for (int j = minIndex; j <= maxIndex; j++)
                            {
                                list.add(m_datas[j].m_close);
                            }
                            linearRegressionEquation(list);
                            getLRBandRange(plot, m_kChart, m_bChart);
                            mpy1 = getChartY(0, plot.m_value1 + m_upSubValue);
                            mpy2 = getChartY(0, plot.m_value2 + m_upSubValue);
                            m_startMovePlot =
                                selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                            if (!m_startMovePlot)
                            {
                                mpy1 = getChartY(0, plot.m_value1 - m_downSubValue);
                                mpy2 = getChartY(0, plot.m_value2 - m_downSubValue);
                                m_startMovePlot =
                                    selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                            }
                        }
                    }
                    else if (plot.m_plotType == "LRChannel")
                    {
                        lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                        double rightX = getSize().cx - m_rightVScaleWidth;
                        double rightY = rightX * m_kChart + m_bChart;
                        m_startMovePlot =
                            selectSegment(mp, mpx1, mpy1, rightX, rightY);
                        if (!m_startMovePlot)
                        {
                            ArrayList<double> list = new ArrayList<double>();
                            int minIndex = Math.Min(index1, index2);
                            int maxIndex = Math.Max(index1, index2);
                            for (int j = minIndex; j <= maxIndex; j++)
                            {
                                list.add(m_datas[j].m_close);
                            }
                            linearRegressionEquation(list);
                            getLRBandRange(plot, m_kChart, m_bChart);
                            mpy1 = getChartY(0, plot.m_value1 + m_upSubValue);
                            mpy2 = getChartY(0, plot.m_value2 + m_upSubValue);
                            lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                            rightY = rightX * m_kChart + m_bChart;
                            m_startMovePlot =
                                selectSegment(mp, mpx1, mpy1, rightX, rightY);
                            if (!m_startMovePlot)
                            {
                                mpy1 = getChartY(0, plot.m_value1 - m_downSubValue);
                                mpy2 = getChartY(0, plot.m_value2 - m_downSubValue);
                                lineXY(mpx1, mpy1, mpx2, mpy2, 0, 0);
                                rightY = rightX * m_kChart + m_bChart;
                                m_startMovePlot =
                                    selectSegment(mp, mpx1, mpy1, rightX, rightY);
                            }
                        }
                    }
                    else if (plot.m_plotType == "ParalleGram")
                    {
                        parallelogram(mpx1, mpy1, mpx2, mpy2, mpx3, mpy3);
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                        if (!m_startMovePlot)
                        {
                            m_startMovePlot =
                                selectSegment(mp, mpx2, mpy2, mpx3, mpy3);
                            if (!m_startMovePlot)
                            {
                                m_startMovePlot = selectSegment(mp, mpx3, mpy3, m_x4Chart, m_y4Chart);
                                if (!m_startMovePlot)
                                {
                                    m_startMovePlot = selectSegment(mp, m_x4Chart, m_y4Chart, mpx1, mpy1);
                                }
                            }
                        }
                    }
                    else if (plot.m_plotType == "SpeedResist")
                    {
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                        if (!m_startMovePlot)
                        {
                            if (mpx1 != mpx2 && mpy1 != mpy2)
                            {
                                FCPoint firstP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) / 3));
                                FCPoint secondP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) * 2 / 3));
                                FCPoint startP = new FCPoint((int)mpx1, (int)mpy1);
                                double fK = 0, fB = 0, sK = 0, sB = 0;
                                lineXY(startP.x, startP.y, firstP.x, firstP.y, 0, 0);
                                fK = m_kChart;
                                fB = m_bChart;
                                lineXY(startP.x, startP.y, secondP.x, secondP.y, 0, 0);
                                sK = m_kChart;
                                sB = m_bChart;
                                double newYF = 0, newYS = 0;
                                double newX = 0;
                                if (mpx2 > mpx1)
                                {
                                    newYF = fK * (getSize().cx - m_rightVScaleWidth) + fB;
                                    newYS = sK * (getSize().cx - m_rightVScaleWidth) + sB;
                                    newX = (getSize().cx - m_rightVScaleWidth);
                                }
                                else
                                {
                                    newYF = fB;
                                    newYS = sB;
                                    newX = m_leftVScaleWidth;
                                }
                                m_startMovePlot =
                                    selectSegment(mp, startP.x, startP.y, newX, newYF);
                                if (!m_startMovePlot)
                                {
                                    m_startMovePlot =
                                        selectSegment(mp, startP.x, startP.y, newX, newYS);
                                }
                            }
                        }
                    }
                    else if (plot.m_plotType == "FiboFanline")
                    {
                        m_startMovePlot = selectSegment(mp, mpx1, mpy1, mpx2, mpy2);
                        if (!m_startMovePlot)
                        {
                            if (mpx1 != mpx2 && mpy1 != mpy2)
                            {
                                FCPoint firstP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) * 0.382));
                                FCPoint secondP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) * 0.5));
                                FCPoint thirdP = new FCPoint((int)mpx2, (int)(mpy2 - (mpy2 - mpy1) * 0.618));
                                FCPoint startP = new FCPoint((int)mpx1, (int)mpy1);
                                ArrayList<FCPoint> listP = new ArrayList<FCPoint>();
                                listP.add(firstP);
                                listP.add(secondP);
                                listP.add(thirdP);
                                int listSize = listP.size();
                                for (int j = 0; j < listSize; j++)
                                {
                                    lineXY(startP.x, startP.y, listP[j].x, listP[j].y, 0, 0);
                                    double newX = 0;
                                    double newY = 0;
                                    if (mpx2 > mpx1)
                                    {
                                        newY = m_kChart * (getSize().cx - m_rightVScaleWidth) +
                                            m_bChart;
                                        newX = (getSize().cx - m_rightVScaleWidth);
                                    }
                                    else
                                    {
                                        newY = m_bChart;
                                        newX = m_leftVScaleWidth;
                                    }
                                    m_startMovePlot =
                                        selectSegment(mp, startP.x, startP.y, newX, newY);
                                    if (m_startMovePlot)
                                    {
                                        break;
                                    }
                                }
                            }
                        }
                    }
                    else if (plot.m_plotType == "FiboTimezone")
                    {
                        int fValue = 1;
                        int aIndex = index1;
                        int pos = 1;
                        int divHeight = getCandleDivHeight();
                        m_startMovePlot =
                            selectSegment(mp, mpx1, 0, mpx1, divHeight);
                        if (!m_startMovePlot)
                        {
                            while (aIndex + fValue <= m_lastVisibleIndex)
                            {
                                fValue = fibonacciValue(pos);
                                int newIndex = aIndex + fValue;
                                int newX = getChartX(newIndex);
                                m_startMovePlot =
                                    selectSegment(mp, newX, 0, newX, divHeight);
                                if (m_startMovePlot)
                                {
                                    break;
                                }
                                pos++;
                            }
                        }
                    }
                    else if (plot.m_plotType == "Percent")
                    {
                        ArrayList<int> list = getPercentParams(mpy1, mpy2);
                        for (int j = 0; j < list.size(); j++)
                        {
                            m_startMovePlot = selectSegment(mp, m_leftVScaleWidth,
                                list[j], getSize().cx - m_rightVScaleWidth, list[j]);
                            if (m_startMovePlot)
                            {
                                break;
                            }
                        }
                    }
                    if (m_startMovePlot)
                    {
                        sPlot = plot;
                        plot.m_startKey1 = plot.m_key1;
                        plot.m_startValue1 = plot.m_value1;
                        plot.m_startKey2 = plot.m_key2;
                        plot.m_startValue2 = plot.m_value2;
                        plot.m_startKey3 = plot.m_key3;
                        plot.m_startValue3 = plot.m_value3;
                        break;
                    }
                }
            }
            return sPlot;
        }

        /// <summary>
        /// 设置可见索引
        /// </summary>
        /// <param name="firstVisibleIndex">起始索引</param>
        /// <param name="lastVisibleIndex">结束索引</param>
        public virtual void setChartVisibleIndex(int firstVisibleIndex, int lastVisibleIndex)
        {
            double xScalePixel =
                getChartWorkAreaWidth() / (lastVisibleIndex - firstVisibleIndex + 1);
            if (xScalePixel < 1000000)
            {
                m_firstVisibleIndex = firstVisibleIndex;
                m_lastVisibleIndex = lastVisibleIndex;
                //设置最后一条记录是否可见
                if (lastVisibleIndex != m_datas.size() - 1)
                {
                    m_lastRecordIsVisible = false;
                }
                else
                {
                    m_lastRecordIsVisible = true;
                }
                m_hScalePixel = xScalePixel;
                checkChartLastVisibleIndex();
            }
        }

        /// <summary>
        /// 判断是否选中线条
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <param name="divIndex">层索引</param>
        /// <param name="datas">数据</param>
        /// <param name="curIndex">当前索引</param>
        /// <returns></returns>
        public virtual bool selectLines(FCPoint mp, int divIndex, ArrayList<double> datas, int curIndex)
        {
            if (datas.size() > 0)
            {
                int topY = getChartY(divIndex, datas[curIndex]);
                if (m_hScalePixel <= 1)
                {
                    if (mp.y >= topY - 8 && mp.y <= topY + 8)
                    {
                        return true;
                    }
                }
                else
                {
                    int index = curIndex;
                    int scaleX = getChartX(index);
                    double judgeTop = 0;
                    double judgeScaleX = scaleX;
                    if (mp.x >= scaleX)
                    {
                        int leftIndex = curIndex + 1;
                        if (curIndex < m_lastVisibleIndex)
                        {
                            double rightValue = datas[leftIndex];
                            judgeTop = getChartY(divIndex, rightValue);
                        }
                        else
                        {
                            judgeTop = topY;
                        }
                    }
                    else
                    {
                        judgeScaleX = scaleX - m_hScalePixel;
                        int rightIndex = curIndex - 1;
                        if (curIndex > 0)
                        {
                            double leftValue = datas[rightIndex];
                            judgeTop = getChartY(divIndex, leftValue);
                        }
                        else
                        {
                            judgeTop = topY;
                        }
                    }
                    double lineWidth = 4;
                    double judgeX = 0, judgeY = 0, judgeW = 0, judgeH = 0;
                    if (judgeTop >= topY)
                    {
                        judgeX = judgeScaleX;
                        judgeY = topY - 2 - lineWidth;
                        judgeW = m_hScalePixel;
                        judgeH = judgeTop - topY + lineWidth < 4
                            ? 4
                            : judgeTop - topY + 4 + lineWidth;
                    }
                    else
                    {
                        judgeX = judgeScaleX;
                        judgeY = judgeTop - 2 - lineWidth / 2;
                        judgeW = m_hScalePixel;
                        judgeH = topY - judgeTop + lineWidth < 4
                            ? 4
                            : topY - judgeTop + 4 + lineWidth;
                    }

                    if (mp.x >= judgeX &&
                        mp.x <= judgeX + judgeW &&
                        mp.y >= judgeY &&
                        mp.y <= judgeY + judgeH)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 判断是否在右轴选中线条
        /// </summary>
        /// <param name="mp">坐标</param>
        /// <param name="divIndex">层索引</param>
        /// <param name="datas">数据</param>
        /// <param name="curIndex">当前索引</param>
        /// <returns></returns>
        public virtual bool selectLinesInRight(FCPoint mp, int divIndex, ArrayList<double> datas, int curIndex)
        {
            if (datas.size() > 0)
            {
                int topY = getChartYInRight(divIndex, datas[curIndex]);
                if (m_hScalePixel <= 1)
                {
                    if (mp.y >= topY - 8 && mp.y <= topY + 8)
                    {
                        return true;
                    }
                }
                else
                {
                    int index = curIndex;
                    int scaleX = getChartX(index);
                    double judgeTop = 0;
                    double judgeScaleX = scaleX;
                    if (mp.x >= scaleX)
                    {
                        int leftIndex = curIndex + 1;
                        if (curIndex < m_lastVisibleIndex)
                        {
                            double rightValue = datas[leftIndex];
                            judgeTop = getChartYInRight(divIndex, rightValue);
                        }
                        else
                        {
                            judgeTop = topY;
                        }
                    }
                    else
                    {
                        judgeScaleX = scaleX - m_hScalePixel;
                        int rightIndex = curIndex - 1;
                        if (curIndex > 0)
                        {
                            double leftValue = datas[rightIndex];
                            judgeTop = getChartYInRight(divIndex, leftValue);
                        }
                        else
                        {
                            judgeTop = topY;
                        }
                    }
                    double lineWidth = 4;
                    double judgeX = 0, judgeY = 0, judgeW = 0, judgeH = 0;
                    if (judgeTop >= topY)
                    {
                        judgeX = judgeScaleX;
                        judgeY = topY - 2 - lineWidth;
                        judgeW = m_hScalePixel;
                        judgeH = judgeTop - topY + lineWidth < 4
                            ? 4
                            : judgeTop - topY + 4 + lineWidth;
                    }
                    else
                    {
                        judgeX = judgeScaleX;
                        judgeY = judgeTop - 2 - lineWidth / 2;
                        judgeW = m_hScalePixel;
                        judgeH = topY - judgeTop + lineWidth < 4
                            ? 4
                            : topY - judgeTop + 4 + lineWidth;
                    }

                    if (mp.x >= judgeX &&
                        mp.x <= judgeX + judgeW &&
                        mp.y >= judgeY &&
                        mp.y <= judgeY + judgeH)
                    {
                        return true;
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 左滚
        /// </summary>
        /// <param name="step">步长</param>
        public virtual void scrollLeftChart(int step)
        {
            m_targetOldX = 0;
            m_targetOldX2 = 0;
            if (m_showCrossLine)
            {
                m_crossStopIndex = m_crossStopIndex - step;
                if (m_crossStopIndex >= m_firstVisibleIndex)
                {
                    step = 0;
                }
                else if (m_crossStopIndex < 0)
                {
                    m_crossStopIndex = 0;
                }
            }
            if (step > 0)
            {
                int subIndex = m_lastVisibleIndex - m_firstVisibleIndex;
                int fIndex = m_firstVisibleIndex - step;
                if (fIndex < 0)
                {
                    fIndex = 0;
                }
                int eIndex = fIndex + subIndex;
                m_firstVisibleIndex = fIndex;
                m_lastVisibleIndex = eIndex;
            }
            checkChartLastVisibleIndex();
            calculateChartMaxMin();
        }

        /// <summary>
        /// 右滚
        /// </summary>
        /// <param name="step">步长</param>
        public virtual void scrollRightChart(int step)
        {
            m_targetOldX = 0;
            m_targetOldX2 = 0;
            int dataCount = m_datas.size();
            if (m_showCrossLine)
            {
                m_crossStopIndex = m_crossStopIndex + step;
                if (m_crossStopIndex <= m_lastVisibleIndex)
                {
                    step = 0;
                }
                else if (m_crossStopIndex > dataCount - 1)
                {
                    m_crossStopIndex = dataCount - 1;
                }
            }
            if (step > 0)
            {
                int subIndex = m_lastVisibleIndex - m_firstVisibleIndex;
                int eIndex = m_lastVisibleIndex + step;
                if (eIndex > dataCount - 1)
                {
                    eIndex = dataCount - 1;
                }
                int fIndex = eIndex - subIndex;
                m_firstVisibleIndex = fIndex;
                m_lastVisibleIndex = eIndex;
            }
            checkChartLastVisibleIndex();
            calculateChartMaxMin();
        }

        /// <summary>
        /// 图表的鼠标按下方法
        /// </summary>
        /// <param name="firstTouch">是否第一次触摸</param>
        /// <param name="firstPoint">第一次触摸的坐标</param>
        /// <param name="secondTouch">是否第二次触摸</param>
        /// <param name="secondPoint">第二次触摸的坐标</param>
        public virtual void touchDownChart(bool firstTouch, FCPoint firstPoint, bool secondTouch, FCPoint secondPoint, int clicks)
        {
            m_touchDownPoint = firstPoint;
            m_crossStopIndex = getChartIndex(firstPoint);
            m_targetOldX = 0;
            m_targetOldX2 = 0;
            m_selectShape = "";
            m_selectShapeEx = "";
            m_sPlot = null;
            if (m_datas.size() > 0)
            {
                FCPlot selectedPlot = selectPlot(firstPoint);
                if (selectedPlot != null)
                {
                    m_sPlot = selectedPlot;
                }
                if (m_sPlot == null)
                {
                    judgeSelectShape(firstPoint);
                }
            }
            if (clicks == 2)
            {
                m_showCrossLine = !m_showCrossLine;
            }
        }

        /// <summary>
        /// 图表的鼠标移动方法
        /// </summary>
        /// <param name="firstTouch">是否第一次触摸</param>
        /// <param name="firstPoint">第一次触摸的坐标</param>
        /// <param name="secondTouch">是否第二次触摸</param>
        /// <param name="secondPoint">第二次触摸的坐标</param>
        public virtual void touchMoveChart(bool firstTouch, FCPoint firstPoint, bool secondTouch, FCPoint secondPoint)
        {
            if (m_datas.size() == 0)
            {
                return;
            }
            FCPoint mp = firstPoint;
            m_targetOldX = 0;
            m_targetOldX2 = 0;
            m_crossStopIndex = getChartIndex(mp);
            m_touchPosition = mp;
            FCPlot sPlot = m_sPlot;
            if (firstTouch && sPlot != null)
            {
                int newIndex = getChartIndex(mp);
                if (newIndex >= 0 && newIndex < m_datas.size())
                {
                    double newDate = getChartDateByIndex(newIndex);
                    double newValue = getCandleDivValue(mp);
                    if (m_selectPlotPoint == 0)
                    {
                        sPlot.m_key1 = newDate;
                        sPlot.m_value1 = newValue;
                    }
                    else if (m_selectPlotPoint == 1)
                    {
                        sPlot.m_key2 = newDate;
                        sPlot.m_value2 = newValue;
                    }
                    else if (m_selectPlotPoint == 2)
                    {
                        sPlot.m_key3 = newDate;
                        sPlot.m_value3 = newValue;
                    }
                    else if (m_startMovePlot)
                    {
                        double bValue = getCandleDivValue(m_touchDownPoint);
                        int bIndex = getChartIndex(m_touchDownPoint);
                        if (sPlot.m_key1 > 0)
                        {
                            sPlot.m_value1 = sPlot.m_startValue1 + (newValue - bValue);
                            int startIndex1 = getChartIndexByDate(sPlot.m_startKey1);
                            int newIndex1 = startIndex1 + (newIndex - bIndex);
                            if (newIndex1 < 0)
                            {
                                newIndex1 = 0;
                            }
                            else if (newIndex1 > m_datas.size() - 1)
                            {
                                newIndex1 = m_datas.size() - 1;
                            }
                            sPlot.m_key1 = getChartDateByIndex(newIndex1);
                        }
                        if (sPlot.m_key2 > 0)
                        {
                            sPlot.m_value2 = sPlot.m_startValue2 + (newValue - bValue);
                            int startIndex2 = getChartIndexByDate(sPlot.m_startKey2);
                            int newIndex2 = startIndex2 + (newIndex - bIndex);
                            if (newIndex2 < 0)
                            {
                                newIndex2 = 0;
                            }
                            else if (newIndex2 > m_datas.size() - 1)
                            {
                                newIndex2 = m_datas.size() - 1;
                            }
                            sPlot.m_key2 = getChartDateByIndex(newIndex2);
                        }
                        if (sPlot.m_key3 > 0)
                        {
                            sPlot.m_value3 = sPlot.m_startValue3 + (newValue - bValue);
                            int startIndex3 = getChartIndexByDate(sPlot.m_startKey3);
                            int newIndex3 = startIndex3 + (newIndex - bIndex);
                            if (newIndex3 < 0)
                            {
                                newIndex3 = 0;
                            }
                            else if (newIndex3 > m_datas.size() - 1)
                            {
                                newIndex3 = m_datas.size() - 1;
                            }
                            sPlot.m_key3 = getChartDateByIndex(newIndex3);
                        }
                    }
                }
                return;
            }
            if (firstTouch && secondTouch)
            {
                if (firstPoint.x > secondPoint.x)
                {
                    m_firstTouchPointCache = secondPoint;
                    m_secondTouchPointCache = firstPoint;
                }
                else
                {
                    m_firstTouchPointCache = firstPoint;
                    m_secondTouchPointCache = secondPoint;
                }
                if (m_firstTouchIndexCache == -1 ||
                    m_secondTouchIndexCache == -1)
                {
                    m_firstTouchIndexCache =
                        getChartIndex(m_firstTouchPointCache);
                    m_secondTouchIndexCache =
                        getChartIndex(m_secondTouchPointCache);
                    m_firstIndexCache = m_firstVisibleIndex;
                    m_lastIndexCache = m_lastVisibleIndex;
                }
            }
            else if (firstTouch)
            {
                m_secondTouchIndexCache = -1;
                if (m_firstTouchIndexCache == -1)
                {
                    m_firstTouchPointCache = firstPoint;
                    m_firstTouchIndexCache =
                        getChartIndex(m_firstTouchPointCache);
                    m_firstIndexCache = m_firstVisibleIndex;
                    m_lastIndexCache = m_lastVisibleIndex;
                    m_firstPaddingTop = m_candlePaddingTop;
                    m_firtstPaddingBottom = m_candlePaddingBottom;
                }
            }

            if (firstTouch && secondTouch)
            {
                if (m_firstTouchIndexCache != -1 &&
                    m_secondTouchIndexCache != -1)
                {
                    FCPoint fPoint = firstPoint;
                    FCPoint sPoint = secondPoint;
                    if (firstPoint.x > secondPoint.x)
                    {
                        fPoint = secondPoint;
                        sPoint = firstPoint;
                    }
                    double subX = Math.Abs(sPoint.x - fPoint.x);
                    int subIndex =
                        Math.Abs(m_secondTouchIndexCache - m_firstTouchIndexCache);
                    if (subX > 0 && subIndex > 0)
                    {
                        double newScalePixel = subX / subIndex;
                        if (newScalePixel >= 3)
                        {
                            double intScalePixel = (int)newScalePixel;
                            newScalePixel = intScalePixel;
                        }
                        if (newScalePixel != m_hScalePixel)
                        {
                            int newFirstIndex = m_firstTouchIndexCache;
                            double thisX = fPoint.x;
                            thisX -= newScalePixel;
                            while (thisX > m_leftVScaleWidth + newScalePixel)
                            {
                                newFirstIndex--;
                                if (newFirstIndex < 0)
                                {
                                    newFirstIndex = 0;
                                    break;
                                }
                                thisX -= newScalePixel;
                            }

                            thisX = sPoint.x;
                            int newSecondIndex = m_secondTouchIndexCache;
                            thisX += newScalePixel;
                            while (
                                thisX < getSize().cx - m_rightVScaleWidth - newScalePixel)
                            {
                                newSecondIndex++;
                                if (newSecondIndex > m_datas.size() - 1)
                                {
                                    newSecondIndex = m_datas.size() - 1;
                                    break;
                                }
                                thisX += newScalePixel;
                            }
                            setChartVisibleIndex(newFirstIndex, newSecondIndex);
                            int maxVisibleRecord = getChartMaxVisibleCount(m_hScalePixel, getChartWorkAreaWidth());
                            while (maxVisibleRecord <
                                    m_lastVisibleIndex - m_firstVisibleIndex + 1 &&
                                m_lastVisibleIndex > m_firstVisibleIndex)
                            {
                                m_lastVisibleIndex--;
                            }
                            checkChartLastVisibleIndex();
                            resetChartVisibleRecord();
                            calculateChartMaxMin();
                        }
                    }
                }
            }
            else if (firstTouch)
            {
                if (!m_autoFillHScale)
                {
                    int subIndex =
                        (int)((m_firstTouchPointCache.x - firstPoint.x) / m_hScalePixel);
                    if (m_allowDragChartDiv)
                    {
                        m_candlePaddingTop = m_firstPaddingTop - (m_firstTouchPointCache.y - firstPoint.y);
                        m_candlePaddingBottom = m_firtstPaddingBottom + (m_firstTouchPointCache.y - firstPoint.y);
                    }
                    int fIndex = m_firstIndexCache + subIndex;
                    int lIndex = m_lastIndexCache + subIndex;
                    if (fIndex > m_datas.size() - 1)
                    {
                        fIndex = m_datas.size() - 1;
                        lIndex = m_datas.size() - 1;
                    }
                    m_firstVisibleIndex = fIndex;
                    m_lastVisibleIndex = lIndex;
                    checkChartLastVisibleIndex();
                    calculateChartMaxMin();
                }
            }
        }

        /// <summary>
        /// 更新布局方法
        /// </summary>
        public override void update()
        {
            base.update();
            resetChartVisibleRecord();
            checkChartLastVisibleIndex();
            calculateChartMaxMin();
        }

        /// <summary>
        /// 缩小
        /// </summary>
        public virtual void zoomOutChart()
        {
            if (!m_autoFillHScale)
            {
                double hScalePixel = m_hScalePixel;
                int oldX = getChartX(m_crossStopIndex);
                if (m_targetOldX == 0)
                {
                    m_targetOldX = oldX;
                }
                int pureH = getChartWorkAreaWidth();
                int oriMax = -1, max = -1, deal = 0;
                int dataCount = m_datas.size();
                int findex = m_firstVisibleIndex, lindex = m_lastVisibleIndex;
                if (hScalePixel < pureH)
                {
                    oriMax = getChartMaxVisibleCount(hScalePixel, pureH);
                    if (dataCount < oriMax)
                    {
                        deal = 1;
                    }
                    if (hScalePixel > 3)
                    {
                        hScalePixel += 1;
                    }
                    else
                    {
                        if (hScalePixel == 1)
                        {
                            hScalePixel = 2;
                        }
                        else
                        {
                            hScalePixel = hScalePixel * 1.5;
                            if (hScalePixel > 3)
                            {
                                hScalePixel = (int)hScalePixel;
                            }
                        }
                    }
                    max = getChartMaxVisibleCount(hScalePixel, pureH);
                    if (dataCount >= max)
                    {
                        if (deal == 1)
                        {
                            lindex = dataCount - 1;
                        }
                        findex = lindex - max + 1;
                        if (findex < 0)
                        {
                            findex = 0;
                        }
                    }
                }
                m_hScalePixel = hScalePixel;
                if (true)
                {
                    float sX = m_targetOldX;
                    findex = m_crossStopIndex;
                    while (sX >= m_leftVScaleWidth + m_hScalePixel / 2)
                    {
                        findex = findex - 1;
                        m_offsetX = (float)(sX - m_leftVScaleWidth - m_hScalePixel / 2);
                        sX = (float)(sX - m_hScalePixel);
                    }
                    findex = findex + 1;
                }
                m_firstVisibleIndex = findex;
                m_lastVisibleIndex = lindex;
                checkChartLastVisibleIndex();
                calculateChartMaxMin();
            }
        }

        /// <summary>
        /// 放大
        /// </summary>
        public virtual void zoomInChart()
        {
            if (!m_autoFillHScale)
            {
                double hScalePixel = m_hScalePixel;
                int oldX = getChartX(m_crossStopIndex);
                if (m_targetOldX2 == 0)
                {
                    m_targetOldX2 = oldX;
                }
                int pureH = getChartWorkAreaWidth();
                int max = -1;
                int dataCount = m_datas.size();
                int findex = m_firstVisibleIndex, lindex = m_lastVisibleIndex;
                if (hScalePixel > 3)
                {
                    hScalePixel -= 1;
                }
                else
                {
                    hScalePixel = hScalePixel * 2 / 3;
                    if (hScalePixel > 3)
                    {
                        hScalePixel = (int)hScalePixel;
                    }
                }
                max = getChartMaxVisibleCount(hScalePixel, pureH);
                if (max >= dataCount)
                {
                    if (hScalePixel < 1)
                    {
                        hScalePixel = pureH / (double)max;
                    }
                    findex = 0;
                    lindex = dataCount - 1;
                }
                else
                {
                    findex = lindex - max + 1;
                    if (findex < 0)
                    {
                        findex = 0;
                    }
                }
                m_hScalePixel = hScalePixel;
                if (true)
                {
                    float sX = m_targetOldX2;
                    findex = m_crossStopIndex;
                    while (sX >= m_leftVScaleWidth + m_hScalePixel / 2)
                    {
                        findex = findex - 1;
                        m_offsetX = (float)(sX - m_leftVScaleWidth - m_hScalePixel / 2);
                        sX = (float)(sX - m_hScalePixel);
                    }
                    findex = findex + 1;
                }
                m_firstVisibleIndex = findex;
                m_lastVisibleIndex = lindex;
                checkChartLastVisibleIndex();
                calculateChartMaxMin();
            }
        }
    }
}